Rework ResourceLoader, ResourceManager and ObjectLibrary
They're no longer static
This commit is contained in:
parent
3437f43af6
commit
a52103a641
|
|
@ -202,13 +202,13 @@ namespace Nz
|
|||
|
||||
using StreamOptionFlags = Flags<StreamOption>;
|
||||
|
||||
enum Ternary
|
||||
enum class Ternary
|
||||
{
|
||||
Ternary_False,
|
||||
Ternary_True,
|
||||
Ternary_Unknown,
|
||||
False,
|
||||
True,
|
||||
Unknown,
|
||||
|
||||
Ternary_Max = Ternary_Unknown
|
||||
Max = Unknown
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -18,6 +18,12 @@ namespace Nz
|
|||
friend class Core;
|
||||
|
||||
public:
|
||||
ModuleBase(const ModuleBase&) = delete;
|
||||
ModuleBase(ModuleBase&&) = delete;
|
||||
|
||||
ModuleBase& operator=(const ModuleBase&) = delete;
|
||||
ModuleBase& operator=(ModuleBase&&) = delete;
|
||||
|
||||
static T* Instance();
|
||||
|
||||
protected:
|
||||
|
|
|
|||
|
|
@ -7,8 +7,7 @@
|
|||
#ifndef NAZARA_OBJECTLIBRARY_HPP
|
||||
#define NAZARA_OBJECTLIBRARY_HPP
|
||||
|
||||
#include <Nazara/Core/ObjectRef.hpp>
|
||||
#include <Nazara/Core/RefCounted.hpp>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
|
|
@ -20,23 +19,20 @@ namespace Nz
|
|||
friend Type;
|
||||
|
||||
public:
|
||||
ObjectLibrary() = delete;
|
||||
~ObjectLibrary() = delete;
|
||||
ObjectLibrary() = default;
|
||||
~ObjectLibrary() = default;
|
||||
|
||||
static void Clear();
|
||||
void Clear();
|
||||
|
||||
static ObjectRef<Type> Get(const std::string& name);
|
||||
static bool Has(const std::string& name);
|
||||
std::shared_ptr<Type> Get(const std::string& name);
|
||||
bool Has(const std::string& name);
|
||||
|
||||
static void Register(const std::string& name, ObjectRef<Type> object);
|
||||
static ObjectRef<Type> Query(const std::string& name);
|
||||
static void Unregister(const std::string& name);
|
||||
void Register(const std::string& name, std::shared_ptr<Type> object);
|
||||
std::shared_ptr<Type> Query(const std::string& name);
|
||||
void Unregister(const std::string& name);
|
||||
|
||||
private:
|
||||
static bool Initialize();
|
||||
static void Uninitialize();
|
||||
|
||||
using LibraryMap = std::unordered_map<std::string, ObjectRef<Type>>;
|
||||
std::unordered_map<std::string, std::shared_ptr<Type>> m_library;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -20,11 +20,11 @@ namespace Nz
|
|||
template<typename Type>
|
||||
void ObjectLibrary<Type>::Clear()
|
||||
{
|
||||
Type::s_library.clear();
|
||||
m_library.clear();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the ObjectRef object by name
|
||||
* \brief Gets the std::shared_ptr object by name
|
||||
* \return Optional reference
|
||||
*
|
||||
* \param name Name of the object
|
||||
|
|
@ -32,9 +32,9 @@ namespace Nz
|
|||
* \remark Produces a NazaraError if object not found
|
||||
*/
|
||||
template<typename Type>
|
||||
ObjectRef<Type> ObjectLibrary<Type>::Get(const std::string& name)
|
||||
std::shared_ptr<Type> ObjectLibrary<Type>::Get(const std::string& name)
|
||||
{
|
||||
ObjectRef<Type> ref = Query(name);
|
||||
std::shared_ptr<Type> ref = Query(name);
|
||||
if (!ref)
|
||||
NazaraError("Object \"" + name + "\" is not present");
|
||||
|
||||
|
|
@ -48,58 +48,46 @@ namespace Nz
|
|||
template<typename Type>
|
||||
bool ObjectLibrary<Type>::Has(const std::string& name)
|
||||
{
|
||||
return Type::s_library.find(name) != Type::s_library.end();
|
||||
return m_library.find(name) != m_library.end();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Registers the ObjectRef object with that name
|
||||
* \brief Registers the std::shared_ptr object with that name
|
||||
*
|
||||
* \param name Name of the object
|
||||
* \param object Object to stock
|
||||
*/
|
||||
template<typename Type>
|
||||
void ObjectLibrary<Type>::Register(const std::string& name, ObjectRef<Type> object)
|
||||
void ObjectLibrary<Type>::Register(const std::string& name, std::shared_ptr<Type> object)
|
||||
{
|
||||
Type::s_library.emplace(name, object);
|
||||
m_library.emplace(name, object);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the ObjectRef object by name
|
||||
* \brief Gets the std::shared_ptr object by name
|
||||
* \return Optional reference
|
||||
*
|
||||
* \param name Name of the object
|
||||
*/
|
||||
template<typename Type>
|
||||
ObjectRef<Type> ObjectLibrary<Type>::Query(const std::string& name)
|
||||
std::shared_ptr<Type> ObjectLibrary<Type>::Query(const std::string& name)
|
||||
{
|
||||
auto it = Type::s_library.find(name);
|
||||
if (it != Type::s_library.end())
|
||||
auto it = m_library.find(name);
|
||||
if (it != m_library.end())
|
||||
return it->second;
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Unregisters the ObjectRef object with that name
|
||||
* \brief Unregisters the std::shared_ptr object with that name
|
||||
*
|
||||
* \param name Name of the object
|
||||
*/
|
||||
template<typename Type>
|
||||
void ObjectLibrary<Type>::Unregister(const std::string& name)
|
||||
{
|
||||
Type::s_library.erase(name);
|
||||
}
|
||||
|
||||
template<typename Type>
|
||||
bool ObjectLibrary<Type>::Initialize()
|
||||
{
|
||||
return true; // Nothing to do
|
||||
}
|
||||
|
||||
template<typename Type>
|
||||
void ObjectLibrary<Type>::Uninitialize()
|
||||
{
|
||||
Type::s_library.clear();
|
||||
m_library.erase(name);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -8,14 +8,13 @@
|
|||
#define NAZARA_RESOURCELOADER_HPP
|
||||
|
||||
#include <Nazara/Core/Enums.hpp>
|
||||
#include <Nazara/Core/ObjectRef.hpp>
|
||||
#include <Nazara/Core/RefCounted.hpp>
|
||||
#include <Nazara/Core/Resource.hpp>
|
||||
#include <Nazara/Core/ResourceParameters.hpp>
|
||||
#include <filesystem>
|
||||
#include <list>
|
||||
#include <tuple>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
|
|
@ -29,27 +28,43 @@ namespace Nz
|
|||
friend Type;
|
||||
|
||||
public:
|
||||
using ExtensionGetter = bool (*)(const std::string& extension);
|
||||
using FileLoader = ObjectRef<Type> (*)(const std::filesystem::path& filePath, const Parameters& parameters);
|
||||
using MemoryLoader = ObjectRef<Type> (*)(const void* data, std::size_t size, const Parameters& parameters);
|
||||
using StreamChecker = Ternary (*)(Stream& stream, const Parameters& parameters);
|
||||
using StreamLoader = ObjectRef<Type> (*)(Stream& stream, const Parameters& parameters);
|
||||
struct Entry;
|
||||
using ExtensionSupport = std::function<bool(const std::string_view& extension)>;
|
||||
using FileLoader = std::function<std::shared_ptr<Type>(const std::filesystem::path& filePath, const Parameters& parameters)>;
|
||||
using MemoryLoader = std::function<std::shared_ptr<Type>(const void* data, std::size_t size, const Parameters& parameters)>;
|
||||
using StreamChecker = std::function<Ternary(Stream& stream, const Parameters& parameters)>;
|
||||
using StreamLoader = std::function<std::shared_ptr<Type>(Stream& stream, const Parameters& parameters)>;
|
||||
|
||||
ResourceLoader() = delete;
|
||||
~ResourceLoader() = delete;
|
||||
ResourceLoader() = default;
|
||||
ResourceLoader(const ResourceLoader&) = delete;
|
||||
ResourceLoader(ResourceLoader&&) noexcept = default;
|
||||
~ResourceLoader() = default;
|
||||
|
||||
static bool IsExtensionSupported(const std::string& extension);
|
||||
void Clear();
|
||||
|
||||
static ObjectRef<Type> LoadFromFile(const std::filesystem::path& filePath, const Parameters& parameters = Parameters());
|
||||
static ObjectRef<Type> LoadFromMemory(const void* data, std::size_t size, const Parameters& parameters = Parameters());
|
||||
static ObjectRef<Type> LoadFromStream(Stream& stream, const Parameters& parameters = Parameters());
|
||||
bool IsExtensionSupported(const std::string_view& extension) const;
|
||||
|
||||
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);
|
||||
std::shared_ptr<Type> LoadFromFile(const std::filesystem::path& filePath, const Parameters& parameters = Parameters()) const;
|
||||
std::shared_ptr<Type> LoadFromMemory(const void* data, std::size_t size, const Parameters& parameters = Parameters()) const;
|
||||
std::shared_ptr<Type> LoadFromStream(Stream& stream, const Parameters& parameters = Parameters()) const;
|
||||
|
||||
const Entry* RegisterLoader(Entry loader);
|
||||
void UnregisterLoader(const Entry* loader);
|
||||
|
||||
ResourceLoader& operator=(const ResourceLoader&) = delete;
|
||||
ResourceLoader& operator=(ResourceLoader&&) noexcept = default;
|
||||
|
||||
struct Entry
|
||||
{
|
||||
ExtensionSupport extensionSupport;
|
||||
FileLoader fileLoader;
|
||||
MemoryLoader memoryLoader;
|
||||
StreamChecker streamChecker;
|
||||
StreamLoader streamLoader;
|
||||
};
|
||||
|
||||
private:
|
||||
using Loader = std::tuple<ExtensionGetter, StreamChecker, StreamLoader, FileLoader, MemoryLoader>;
|
||||
using LoaderList = std::list<Loader>;
|
||||
std::vector<std::unique_ptr<Entry>> m_loaders;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -18,20 +18,29 @@ namespace Nz
|
|||
* \brief Core class that represents a loader of resources
|
||||
*/
|
||||
|
||||
/*!
|
||||
* \brief Unregister every loader registered
|
||||
*/
|
||||
template<typename Type, typename Parameters>
|
||||
void ResourceLoader<Type, Parameters>::Clear()
|
||||
{
|
||||
m_loaders.clear();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Checks whether the extension of the file is supported
|
||||
* \return true if supported
|
||||
*
|
||||
* \param extension Extension of the file
|
||||
* \param extension Extension of the file (ex: "png")
|
||||
*/
|
||||
template<typename Type, typename Parameters>
|
||||
bool ResourceLoader<Type, Parameters>::IsExtensionSupported(const std::string& extension)
|
||||
bool ResourceLoader<Type, Parameters>::IsExtensionSupported(const std::string_view& extension) const
|
||||
{
|
||||
for (Loader& loader : Type::s_loaders)
|
||||
for (auto& loaderPtr : m_loaders)
|
||||
{
|
||||
ExtensionGetter isExtensionSupported = std::get<0>(loader);
|
||||
const Entry& loader = *loaderPtr;
|
||||
|
||||
if (isExtensionSupported && isExtensionSupported(extension))
|
||||
if (loader.extensionSupport && loader.extensionSupport(extension))
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -54,7 +63,7 @@ namespace Nz
|
|||
* \remark Produces a NazaraError if all loaders failed or no loader was found
|
||||
*/
|
||||
template<typename Type, typename Parameters>
|
||||
ObjectRef<Type> ResourceLoader<Type, Parameters>::LoadFromFile(const std::filesystem::path& filePath, const Parameters& parameters)
|
||||
std::shared_ptr<Type> ResourceLoader<Type, Parameters>::LoadFromFile(const std::filesystem::path& filePath, const Parameters& parameters) const
|
||||
{
|
||||
NazaraAssert(parameters.IsValid(), "Invalid parameters");
|
||||
|
||||
|
|
@ -71,17 +80,14 @@ namespace Nz
|
|||
File file(filePath.generic_u8string()); // Open only if needed
|
||||
|
||||
bool found = false;
|
||||
for (Loader& loader : Type::s_loaders)
|
||||
for (auto& loaderPtr : m_loaders)
|
||||
{
|
||||
ExtensionGetter isExtensionSupported = std::get<0>(loader);
|
||||
if (!isExtensionSupported || !isExtensionSupported(ext))
|
||||
const Entry& loader = *loaderPtr;
|
||||
|
||||
if (loader.extensionSupport && !loader.extensionSupport(ext))
|
||||
continue;
|
||||
|
||||
StreamChecker checkFunc = std::get<1>(loader);
|
||||
StreamLoader streamLoader = std::get<2>(loader);
|
||||
FileLoader fileLoader = std::get<3>(loader);
|
||||
|
||||
if (checkFunc && !file.IsOpen())
|
||||
if (loader.streamChecker && !file.IsOpen())
|
||||
{
|
||||
if (!file.Open(OpenMode_ReadOnly))
|
||||
{
|
||||
|
|
@ -90,26 +96,26 @@ namespace Nz
|
|||
}
|
||||
}
|
||||
|
||||
Ternary recognized = Ternary_Unknown;
|
||||
if (fileLoader)
|
||||
Ternary recognized = Ternary::Unknown;
|
||||
if (loader.fileLoader)
|
||||
{
|
||||
if (checkFunc)
|
||||
if (loader.streamChecker)
|
||||
{
|
||||
file.SetCursorPos(0);
|
||||
|
||||
recognized = checkFunc(file, parameters);
|
||||
if (recognized == Ternary_False)
|
||||
recognized = loader.streamChecker(file, parameters);
|
||||
if (recognized == Ternary::False)
|
||||
continue;
|
||||
else
|
||||
found = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
recognized = Ternary_Unknown;
|
||||
recognized = Ternary::Unknown;
|
||||
found = true;
|
||||
}
|
||||
|
||||
ObjectRef<Type> resource = fileLoader(filePath, parameters);
|
||||
std::shared_ptr<Type> resource = loader.fileLoader(filePath, parameters);
|
||||
if (resource)
|
||||
{
|
||||
resource->SetFilePath(filePath);
|
||||
|
|
@ -118,17 +124,19 @@ namespace Nz
|
|||
}
|
||||
else
|
||||
{
|
||||
assert(loader.streamChecker);
|
||||
|
||||
file.SetCursorPos(0);
|
||||
|
||||
recognized = checkFunc(file, parameters);
|
||||
if (recognized == Ternary_False)
|
||||
recognized = loader.streamChecker(file, parameters);
|
||||
if (recognized == Ternary::False)
|
||||
continue;
|
||||
else if (recognized == Ternary_True)
|
||||
else if (recognized == Ternary::True)
|
||||
found = true;
|
||||
|
||||
file.SetCursorPos(0);
|
||||
|
||||
ObjectRef<Type> resource = streamLoader(file, parameters);
|
||||
std::shared_ptr<Type> resource = loader.streamLoader(file, parameters);
|
||||
if (resource)
|
||||
{
|
||||
resource->SetFilePath(filePath);
|
||||
|
|
@ -136,7 +144,7 @@ namespace Nz
|
|||
}
|
||||
}
|
||||
|
||||
if (recognized == Ternary_True)
|
||||
if (recognized == Ternary::True)
|
||||
NazaraWarning("Loader failed");
|
||||
}
|
||||
|
||||
|
|
@ -164,7 +172,7 @@ namespace Nz
|
|||
* \remark Produces a NazaraError if all loaders failed or no loader was found
|
||||
*/
|
||||
template<typename Type, typename Parameters>
|
||||
ObjectRef<Type> ResourceLoader<Type, Parameters>::LoadFromMemory(const void* data, std::size_t size, const Parameters& parameters)
|
||||
std::shared_ptr<Type> ResourceLoader<Type, Parameters>::LoadFromMemory(const void* data, std::size_t size, const Parameters& parameters) const
|
||||
{
|
||||
NazaraAssert(data, "Invalid data pointer");
|
||||
NazaraAssert(size, "No data to load");
|
||||
|
|
@ -173,32 +181,30 @@ namespace Nz
|
|||
MemoryView stream(data, size);
|
||||
|
||||
bool found = false;
|
||||
for (Loader& loader : Type::s_loaders)
|
||||
for (auto& loaderPtr : m_loaders)
|
||||
{
|
||||
StreamChecker checkFunc = std::get<1>(loader);
|
||||
StreamLoader streamLoader = std::get<2>(loader);
|
||||
MemoryLoader memoryLoader = std::get<4>(loader);
|
||||
const Entry& loader = *loaderPtr;
|
||||
|
||||
Ternary recognized = Ternary_Unknown;
|
||||
if (memoryLoader)
|
||||
Ternary recognized = Ternary::Unknown;
|
||||
if (loader.memoryLoader)
|
||||
{
|
||||
if (checkFunc)
|
||||
if (loader.streamChecker)
|
||||
{
|
||||
stream.SetCursorPos(0);
|
||||
|
||||
recognized = checkFunc(stream, parameters);
|
||||
if (recognized == Ternary_False)
|
||||
recognized = loader.streamChecker(stream, parameters);
|
||||
if (recognized == Ternary::False)
|
||||
continue;
|
||||
else
|
||||
found = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
recognized = Ternary_Unknown;
|
||||
recognized = Ternary::Unknown;
|
||||
found = true;
|
||||
}
|
||||
|
||||
ObjectRef<Type> resource = memoryLoader(data, size, parameters);
|
||||
std::shared_ptr<Type> resource = loader.memoryLoader(data, size, parameters);
|
||||
if (resource)
|
||||
return resource;
|
||||
}
|
||||
|
|
@ -206,20 +212,20 @@ namespace Nz
|
|||
{
|
||||
stream.SetCursorPos(0);
|
||||
|
||||
recognized = checkFunc(stream, parameters);
|
||||
if (recognized == Ternary_False)
|
||||
recognized = loader.streamChecker(stream, parameters);
|
||||
if (recognized == Ternary::False)
|
||||
continue;
|
||||
else if (recognized == Ternary_True)
|
||||
else if (recognized == Ternary::True)
|
||||
found = true;
|
||||
|
||||
stream.SetCursorPos(0);
|
||||
|
||||
ObjectRef<Type> resource = streamLoader(stream, parameters);
|
||||
std::shared_ptr<Type> resource = loader.streamLoader(stream, parameters);
|
||||
if (resource)
|
||||
return resource;
|
||||
}
|
||||
|
||||
if (recognized == Ternary_True)
|
||||
if (recognized == Ternary::True)
|
||||
NazaraWarning("Loader failed");
|
||||
}
|
||||
|
||||
|
|
@ -246,36 +252,35 @@ namespace Nz
|
|||
* \remark Produces a NazaraError if all loaders failed or no loader was found
|
||||
*/
|
||||
template<typename Type, typename Parameters>
|
||||
ObjectRef<Type> ResourceLoader<Type, Parameters>::LoadFromStream(Stream& stream, const Parameters& parameters)
|
||||
std::shared_ptr<Type> ResourceLoader<Type, Parameters>::LoadFromStream(Stream& stream, const Parameters& parameters) const
|
||||
{
|
||||
NazaraAssert(stream.GetCursorPos() < stream.GetSize(), "No data to load");
|
||||
NazaraAssert(parameters.IsValid(), "Invalid parameters");
|
||||
|
||||
UInt64 streamPos = stream.GetCursorPos();
|
||||
bool found = false;
|
||||
for (Loader& loader : Type::s_loaders)
|
||||
for (auto& loaderPtr : m_loaders)
|
||||
{
|
||||
StreamChecker checkFunc = std::get<1>(loader);
|
||||
StreamLoader streamLoader = std::get<2>(loader);
|
||||
const Entry& loader = *loaderPtr;
|
||||
|
||||
stream.SetCursorPos(streamPos);
|
||||
|
||||
// Does the loader support these data ?
|
||||
Ternary recognized = checkFunc(stream, parameters);
|
||||
if (recognized == Ternary_False)
|
||||
Ternary recognized = loader.streamChecker(stream, parameters);
|
||||
if (recognized == Ternary::False)
|
||||
continue;
|
||||
else if (recognized == Ternary_True)
|
||||
else if (recognized == Ternary::True)
|
||||
found = true;
|
||||
|
||||
// We move the stream to its old position
|
||||
stream.SetCursorPos(streamPos);
|
||||
|
||||
// Load of the resource
|
||||
ObjectRef<Type> resource = streamLoader(stream, parameters);
|
||||
std::shared_ptr<Type> resource = loader.streamLoader(stream, parameters);
|
||||
if (resource)
|
||||
return resource;
|
||||
|
||||
if (recognized == Ternary_True)
|
||||
if (recognized == Ternary::True)
|
||||
NazaraWarning("Loader failed");
|
||||
}
|
||||
|
||||
|
|
@ -289,35 +294,35 @@ namespace Nz
|
|||
|
||||
/*!
|
||||
* \brief Registers the loader
|
||||
* \return A pointer to the registered Load which can be unsed to unregister it later
|
||||
*
|
||||
* \param extensionGetter A function to test whether the extension (as a string) is supported by this loader
|
||||
* \param checkFunc A function to check the stream with the parser
|
||||
* \param streamLoader A function to load the data from a stream in the resource
|
||||
* \param fileLoader Optional function to load the data from a file in the resource
|
||||
* \param memoryLoader Optional function to load the data from a raw memory in the resource
|
||||
* \param loader A collection of loader callbacks that will be registered
|
||||
*
|
||||
* \seealso UnregisterLoader
|
||||
*/
|
||||
template<typename Type, typename Parameters>
|
||||
void ResourceLoader<Type, Parameters>::RegisterLoader(ExtensionGetter extensionGetter, StreamChecker checkFunc, StreamLoader streamLoader, FileLoader fileLoader, MemoryLoader memoryLoader)
|
||||
auto ResourceLoader<Type, Parameters>::RegisterLoader(Entry loader) -> const Entry*
|
||||
{
|
||||
NazaraAssert(checkFunc || !streamLoader, "StreamLoader present without StreamChecker");
|
||||
NazaraAssert(fileLoader || memoryLoader || streamLoader, "A loader function is mandatory");
|
||||
NazaraAssert(loader.streamChecker || !loader.streamLoader, "StreamLoader present without StreamChecker");
|
||||
NazaraAssert(loader.fileLoader || loader.memoryLoader || loader.streamLoader, "A loader function is mandatory");
|
||||
|
||||
Type::s_loaders.push_front(std::make_tuple(extensionGetter, checkFunc, streamLoader, fileLoader, memoryLoader));
|
||||
auto it = m_loaders.emplace(m_loaders.begin(), std::make_unique<Entry>(std::move(loader)));
|
||||
return it->get();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Unregisters the loader
|
||||
*
|
||||
* \param extensionGetter A function to test whether the extension (as a string) is supported by this loader
|
||||
* \param checkFunc A function to check the stream with the parser
|
||||
* \param streamLoader A function to load the data from a stream in the resource
|
||||
* \param fileLoader Optional function to load the data from a file in the resource
|
||||
* \param memoryLoader Optional function to load the data from a raw memory in the resource
|
||||
* \param loader A pointer to a loader returned by RegisterLoad
|
||||
*
|
||||
* \seealso RegisterLoader
|
||||
*/
|
||||
template<typename Type, typename Parameters>
|
||||
void ResourceLoader<Type, Parameters>::UnregisterLoader(ExtensionGetter extensionGetter, StreamChecker checkFunc, StreamLoader streamLoader, FileLoader fileLoader, MemoryLoader memoryLoader)
|
||||
void ResourceLoader<Type, Parameters>::UnregisterLoader(const Entry* loader)
|
||||
{
|
||||
Type::s_loaders.remove(std::make_tuple(extensionGetter, checkFunc, streamLoader, fileLoader, memoryLoader));
|
||||
auto it = std::find_if(m_loaders.begin(), m_loaders.end(), [&](const std::unique_ptr<Entry>& loaderPtr) { return loaderPtr.get() == loader; });
|
||||
if (it != m_loaders.end())
|
||||
m_loaders.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -7,9 +7,9 @@
|
|||
#ifndef NAZARA_RESOURCEMANAGER_HPP
|
||||
#define NAZARA_RESOURCEMANAGER_HPP
|
||||
|
||||
#include <Nazara/Core/ObjectRef.hpp>
|
||||
#include <Nazara/Core/ResourceParameters.hpp>
|
||||
#include <Nazara/Core/ResourceLoader.hpp>
|
||||
#include <filesystem>
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace Nz
|
||||
|
|
@ -17,26 +17,27 @@ namespace Nz
|
|||
template<typename Type, typename Parameters>
|
||||
class ResourceManager
|
||||
{
|
||||
friend Type;
|
||||
|
||||
public:
|
||||
ResourceManager() = delete;
|
||||
~ResourceManager() = delete;
|
||||
using Loader = ResourceLoader<Type, Parameters>;
|
||||
|
||||
static void Clear();
|
||||
ResourceManager(Loader& loader);
|
||||
explicit ResourceManager(const ResourceManager&) = default;
|
||||
ResourceManager(ResourceManager&&) noexcept = default;
|
||||
~ResourceManager() = default;
|
||||
|
||||
static ObjectRef<Type> Get(const std::filesystem::path& filePath);
|
||||
static const Parameters& GetDefaultParameters();
|
||||
void Clear();
|
||||
|
||||
static void Purge();
|
||||
static void Register(const std::filesystem::path& filePath, ObjectRef<Type> resource);
|
||||
static void SetDefaultParameters(const Parameters& params);
|
||||
static void Unregister(const std::filesystem::path& filePath);
|
||||
std::shared_ptr<Type> Get(const std::filesystem::path& filePath);
|
||||
const Parameters& GetDefaultParameters();
|
||||
|
||||
void Register(const std::filesystem::path& filePath, std::shared_ptr<Type> resource);
|
||||
void SetDefaultParameters(Parameters params);
|
||||
void Unregister(const std::filesystem::path& filePath);
|
||||
|
||||
ResourceManager& operator=(const ResourceManager&) = delete;
|
||||
ResourceManager& operator=(ResourceManager&&) = delete;
|
||||
|
||||
private:
|
||||
static bool Initialize();
|
||||
static void Uninitialize();
|
||||
|
||||
// https://stackoverflow.com/questions/51065244/is-there-no-standard-hash-for-stdfilesystempath
|
||||
struct PathHash
|
||||
{
|
||||
|
|
@ -46,8 +47,9 @@ namespace Nz
|
|||
}
|
||||
};
|
||||
|
||||
using ManagerMap = std::unordered_map<std::filesystem::path, ObjectRef<Type>, PathHash>;
|
||||
using ManagerParams = Parameters;
|
||||
std::unordered_map<std::filesystem::path, std::shared_ptr<Type>, PathHash> m_resources;
|
||||
Loader& m_loader;
|
||||
Parameters m_defaultParameters;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -15,13 +15,23 @@ namespace Nz
|
|||
* \brief Core class that represents a resource manager
|
||||
*/
|
||||
|
||||
|
||||
/*!
|
||||
* \brief Clears the content of the manager
|
||||
*/
|
||||
template<typename Type, typename Parameters>
|
||||
ResourceManager<Type, Parameters>::ResourceManager(Loader& loader) :
|
||||
m_loader(loader)
|
||||
{
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Clears the content of the manager
|
||||
*/
|
||||
template<typename Type, typename Parameters>
|
||||
void ResourceManager<Type, Parameters>::Clear()
|
||||
{
|
||||
Type::s_managerMap.clear();
|
||||
m_resources.clear();
|
||||
}
|
||||
|
||||
/*!
|
||||
|
|
@ -31,22 +41,22 @@ namespace Nz
|
|||
* \param filePath Path to the asset that will be loaded
|
||||
*/
|
||||
template<typename Type, typename Parameters>
|
||||
ObjectRef<Type> ResourceManager<Type, Parameters>::Get(const std::filesystem::path& filePath)
|
||||
std::shared_ptr<Type> ResourceManager<Type, Parameters>::Get(const std::filesystem::path& filePath)
|
||||
{
|
||||
std::filesystem::path absolutePath = std::filesystem::canonical(filePath);
|
||||
auto it = Type::s_managerMap.find(absolutePath);
|
||||
if (it == Type::s_managerMap.end())
|
||||
auto it = m_resources.find(absolutePath);
|
||||
if (it == m_resources.end())
|
||||
{
|
||||
ObjectRef<Type> resource = Type::LoadFromFile(absolutePath, GetDefaultParameters());
|
||||
std::shared_ptr<Type> resource = m_loader.LoadFromFile(absolutePath, GetDefaultParameters());
|
||||
if (!resource)
|
||||
{
|
||||
NazaraError("Failed to load resource from file: " + absolutePath.generic_u8string());
|
||||
return ObjectRef<Type>();
|
||||
return std::shared_ptr<Type>();
|
||||
}
|
||||
|
||||
NazaraDebug("Loaded resource from file " + absolutePath.generic_u8string());
|
||||
|
||||
it = Type::s_managerMap.insert(std::make_pair(absolutePath, resource)).first;
|
||||
it = m_resources.insert(std::make_pair(absolutePath, resource)).first;
|
||||
}
|
||||
|
||||
return it->second;
|
||||
|
|
@ -59,27 +69,7 @@ namespace Nz
|
|||
template<typename Type, typename Parameters>
|
||||
const Parameters& ResourceManager<Type, Parameters>::GetDefaultParameters()
|
||||
{
|
||||
return Type::s_managerParameters;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Purges the resource manager from every asset whose it is the only owner
|
||||
*/
|
||||
template<typename Type, typename Parameters>
|
||||
void ResourceManager<Type, Parameters>::Purge()
|
||||
{
|
||||
auto it = Type::s_managerMap.begin();
|
||||
while (it != Type::s_managerMap.end())
|
||||
{
|
||||
const ObjectRef<Type>& ref = it->second;
|
||||
if (ref->GetReferenceCount() == 1) // Are we the only ones to own the resource ?
|
||||
{
|
||||
NazaraDebug("Purging resource from file " + ref->GetFilePath().generic_u8string());
|
||||
Type::s_managerMap.erase(it++); // Then we erase it
|
||||
}
|
||||
else
|
||||
++it;
|
||||
}
|
||||
return m_defaultParameters;
|
||||
}
|
||||
|
||||
/*!
|
||||
|
|
@ -89,11 +79,11 @@ namespace Nz
|
|||
* \param resource Object to associate with
|
||||
*/
|
||||
template<typename Type, typename Parameters>
|
||||
void ResourceManager<Type, Parameters>::Register(const std::filesystem::path& filePath, ObjectRef<Type> resource)
|
||||
void ResourceManager<Type, Parameters>::Register(const std::filesystem::path& filePath, std::shared_ptr<Type> resource)
|
||||
{
|
||||
std::filesystem::path absolutePath = std::filesystem::canonical(filePath);
|
||||
|
||||
Type::s_managerMap[absolutePath] = resource;
|
||||
m_resources[absolutePath] = resource;
|
||||
}
|
||||
|
||||
/*!
|
||||
|
|
@ -102,9 +92,9 @@ namespace Nz
|
|||
* \param params Default parameters for loading from file
|
||||
*/
|
||||
template<typename Type, typename Parameters>
|
||||
void ResourceManager<Type, Parameters>::SetDefaultParameters(const Parameters& params)
|
||||
void ResourceManager<Type, Parameters>::SetDefaultParameters(Parameters params)
|
||||
{
|
||||
Type::s_managerParameters = params;
|
||||
m_defaultParameters = std::move(params);
|
||||
}
|
||||
|
||||
/*!
|
||||
|
|
@ -117,26 +107,7 @@ namespace Nz
|
|||
{
|
||||
std::filesystem::path absolutePath = std::filesystem::canonical(filePath);
|
||||
|
||||
Type::s_managerMap.erase(absolutePath);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Initializes the resource manager
|
||||
* \return true
|
||||
*/
|
||||
template<typename Type, typename Parameters>
|
||||
bool ResourceManager<Type, Parameters>::Initialize()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Uninitialize the resource manager
|
||||
*/
|
||||
template<typename Type, typename Parameters>
|
||||
void ResourceManager<Type, Parameters>::Uninitialize()
|
||||
{
|
||||
Clear();
|
||||
m_resources.erase(absolutePath);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -84,9 +84,9 @@ Ternary CheckAnimation(Stream& /*stream*/, const AnimationParams& parameters)
|
|||
{
|
||||
bool skip;
|
||||
if (parameters.custom.GetBooleanParameter("SkipAssimpLoader", &skip) && skip)
|
||||
return Ternary_False;
|
||||
return Ternary::False;
|
||||
|
||||
return Ternary_Unknown;
|
||||
return Ternary::Unknown;
|
||||
}
|
||||
|
||||
AnimationRef LoadAnimation(Stream& stream, const AnimationParams& parameters)
|
||||
|
|
@ -179,9 +179,9 @@ Ternary CheckMesh(Stream& /*stream*/, const MeshParams& parameters)
|
|||
{
|
||||
bool skip;
|
||||
if (parameters.custom.GetBooleanParameter("SkipAssimpLoader", &skip) && skip)
|
||||
return Ternary_False;
|
||||
return Ternary::False;
|
||||
|
||||
return Ternary_Unknown;
|
||||
return Ternary::Unknown;
|
||||
}
|
||||
|
||||
MeshRef LoadMesh(Stream& stream, const MeshParams& parameters)
|
||||
|
|
|
|||
|
|
@ -245,10 +245,10 @@ namespace Nz
|
|||
if (file)
|
||||
{
|
||||
sf_close(file);
|
||||
return Ternary_True;
|
||||
return Ternary::True;
|
||||
}
|
||||
else
|
||||
return Ternary_False;
|
||||
return Ternary::False;
|
||||
}
|
||||
|
||||
SoundStreamRef LoadSoundStreamFile(const std::filesystem::path& filePath, const SoundStreamParams& parameters)
|
||||
|
|
@ -301,10 +301,10 @@ namespace Nz
|
|||
if (file)
|
||||
{
|
||||
sf_close(file);
|
||||
return Ternary_True;
|
||||
return Ternary::True;
|
||||
}
|
||||
else
|
||||
return Ternary_False;
|
||||
return Ternary::False;
|
||||
}
|
||||
|
||||
SoundBufferRef LoadSoundBuffer(Stream& stream, const SoundBufferParams& parameters)
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ namespace Nz
|
|||
{
|
||||
bool skip;
|
||||
if (parameters.custom.GetBooleanParameter("SkipNativeDDSLoader", &skip) && skip)
|
||||
return Ternary_False;
|
||||
return Ternary::False;
|
||||
|
||||
ByteStream byteStream(&stream);
|
||||
byteStream.SetDataEndianness(Endianness_LittleEndian);
|
||||
|
|
@ -35,7 +35,7 @@ namespace Nz
|
|||
UInt32 magic;
|
||||
byteStream >> magic;
|
||||
|
||||
return (magic == DDS_Magic) ? Ternary_True : Ternary_False;
|
||||
return (magic == DDS_Magic) ? Ternary::True : Ternary::False;
|
||||
}
|
||||
|
||||
static ImageRef Load(Stream& stream, const ImageParams& parameters)
|
||||
|
|
|
|||
|
|
@ -398,15 +398,15 @@ namespace Nz
|
|||
{
|
||||
bool skip;
|
||||
if (parameters.custom.GetBooleanParameter("SkipNativeFreeTypeLoader", &skip) && skip)
|
||||
return Ternary_False;
|
||||
return Ternary::False;
|
||||
|
||||
FreeTypeStream face;
|
||||
face.SetStream(stream);
|
||||
|
||||
if (face.Check())
|
||||
return Ternary_True;
|
||||
return Ternary::True;
|
||||
else
|
||||
return Ternary_False;
|
||||
return Ternary::False;
|
||||
}
|
||||
|
||||
FontRef LoadFile(const std::filesystem::path& filePath, const FontParams& parameters)
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ namespace Nz
|
|||
{
|
||||
bool skip;
|
||||
if (parameters.custom.GetBooleanParameter("SkipNativeMD2Loader", &skip) && skip)
|
||||
return Ternary_False;
|
||||
return Ternary::False;
|
||||
|
||||
UInt32 magic[2];
|
||||
if (stream.Read(&magic[0], 2*sizeof(UInt32)) == 2*sizeof(UInt32))
|
||||
|
|
@ -40,10 +40,10 @@ namespace Nz
|
|||
#endif
|
||||
|
||||
if (magic[0] == md2Ident && magic[1] == 8)
|
||||
return Ternary_True;
|
||||
return Ternary::True;
|
||||
}
|
||||
|
||||
return Ternary_False;
|
||||
return Ternary::False;
|
||||
}
|
||||
|
||||
MeshRef Load(Stream& stream, const MeshParams& parameters)
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ namespace Nz
|
|||
{
|
||||
bool skip;
|
||||
if (parameters.custom.GetBooleanParameter("SkipNativeMD5AnimLoader", &skip) && skip)
|
||||
return Ternary_False;
|
||||
return Ternary::False;
|
||||
|
||||
MD5AnimParser parser(stream);
|
||||
return parser.Check();
|
||||
|
|
|
|||
|
|
@ -37,11 +37,11 @@ namespace Nz
|
|||
if (std::sscanf(&m_currentLine[0], " MD5Version %u", &version) == 1)
|
||||
{
|
||||
if (version == 10)
|
||||
return Ternary_True;
|
||||
return Ternary::True;
|
||||
}
|
||||
}
|
||||
|
||||
return Ternary_False;
|
||||
return Ternary::False;
|
||||
}
|
||||
|
||||
UInt32 MD5AnimParser::GetAnimatedComponentCount() const
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ namespace Nz
|
|||
{
|
||||
bool skip;
|
||||
if (parameters.custom.GetBooleanParameter("SkipNativeMD5MeshLoader", &skip) && skip)
|
||||
return Ternary_False;
|
||||
return Ternary::False;
|
||||
|
||||
MD5MeshParser parser(stream);
|
||||
return parser.Check();
|
||||
|
|
|
|||
|
|
@ -37,11 +37,11 @@ namespace Nz
|
|||
if (std::sscanf(&m_currentLine[0], " MD5Version %u", &version) == 1)
|
||||
{
|
||||
if (version == 10)
|
||||
return Ternary_True;
|
||||
return Ternary::True;
|
||||
}
|
||||
}
|
||||
|
||||
return Ternary_False;
|
||||
return Ternary::False;
|
||||
}
|
||||
|
||||
const MD5MeshParser::Joint* MD5MeshParser::GetJoints() const
|
||||
|
|
|
|||
|
|
@ -33,13 +33,13 @@ namespace Nz
|
|||
|
||||
bool skip;
|
||||
if (parameters.custom.GetBooleanParameter("SkipNativeOBJLoader", &skip) && skip)
|
||||
return Ternary_False;
|
||||
return Ternary::False;
|
||||
|
||||
OBJParser parser;
|
||||
if (!parser.Check(stream))
|
||||
return Ternary_False;
|
||||
return Ternary::False;
|
||||
|
||||
return Ternary_Unknown;
|
||||
return Ternary::Unknown;
|
||||
}
|
||||
|
||||
bool ParseMTL(Mesh* mesh, const std::filesystem::path& filePath, const std::string* materials, const OBJParser::Mesh* meshes, std::size_t meshCount)
|
||||
|
|
|
|||
|
|
@ -49,16 +49,16 @@ namespace Nz
|
|||
{
|
||||
bool skip;
|
||||
if (parameters.custom.GetBooleanParameter("SkipNativePCXLoader", &skip) && skip)
|
||||
return Ternary_False;
|
||||
return Ternary::False;
|
||||
|
||||
UInt8 manufacturer;
|
||||
if (stream.Read(&manufacturer, 1) == 1)
|
||||
{
|
||||
if (manufacturer == 0x0a)
|
||||
return Ternary_True;
|
||||
return Ternary::True;
|
||||
}
|
||||
|
||||
return Ternary_False;
|
||||
return Ternary::False;
|
||||
}
|
||||
|
||||
ImageRef Load(Stream& stream, const ImageParams& parameters)
|
||||
|
|
|
|||
|
|
@ -46,13 +46,13 @@ namespace Nz
|
|||
{
|
||||
bool skip;
|
||||
if (parameters.custom.GetBooleanParameter("SkipNativeSTBLoader", &skip) && skip)
|
||||
return Ternary_False;
|
||||
return Ternary::False;
|
||||
|
||||
int width, height, bpp;
|
||||
if (stbi_info_from_callbacks(&callbacks, &stream, &width, &height, &bpp))
|
||||
return Ternary_True;
|
||||
return Ternary::True;
|
||||
else
|
||||
return Ternary_False;
|
||||
return Ternary::False;
|
||||
}
|
||||
|
||||
ImageRef Load(Stream& stream, const ImageParams& parameters)
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ SCENARIO("SoundBuffer", "[AUDIO][SOUNDBUFFER]")
|
|||
{
|
||||
WHEN("We load our sound")
|
||||
{
|
||||
Nz::SoundBufferRef soundBuffer = Nz::SoundBuffer::LoadFromFile(GetResourceDir() / "Engine/Audio/Cat.flac");
|
||||
Nz::std::shared_ptr<SoundBuffer> soundBuffer = Nz::SoundBuffer::LoadFromFile(GetResourceDir() / "Engine/Audio/Cat.flac");
|
||||
REQUIRE(soundBuffer.IsValid());
|
||||
|
||||
THEN("We can ask the informations of the file")
|
||||
|
|
|
|||
Loading…
Reference in New Issue