Rework ResourceLoader, ResourceManager and ObjectLibrary

They're no longer static
This commit is contained in:
Jérôme Leclercq 2021-05-22 18:20:05 +02:00
parent 3437f43af6
commit a52103a641
21 changed files with 217 additions and 234 deletions

View File

@ -202,13 +202,13 @@ namespace Nz
using StreamOptionFlags = Flags<StreamOption>; using StreamOptionFlags = Flags<StreamOption>;
enum Ternary enum class Ternary
{ {
Ternary_False, False,
Ternary_True, True,
Ternary_Unknown, Unknown,
Ternary_Max = Ternary_Unknown Max = Unknown
}; };
} }

View File

@ -18,6 +18,12 @@ namespace Nz
friend class Core; friend class Core;
public: public:
ModuleBase(const ModuleBase&) = delete;
ModuleBase(ModuleBase&&) = delete;
ModuleBase& operator=(const ModuleBase&) = delete;
ModuleBase& operator=(ModuleBase&&) = delete;
static T* Instance(); static T* Instance();
protected: protected:

View File

@ -7,8 +7,7 @@
#ifndef NAZARA_OBJECTLIBRARY_HPP #ifndef NAZARA_OBJECTLIBRARY_HPP
#define NAZARA_OBJECTLIBRARY_HPP #define NAZARA_OBJECTLIBRARY_HPP
#include <Nazara/Core/ObjectRef.hpp> #include <memory>
#include <Nazara/Core/RefCounted.hpp>
#include <string> #include <string>
#include <unordered_map> #include <unordered_map>
@ -20,23 +19,20 @@ namespace Nz
friend Type; friend Type;
public: public:
ObjectLibrary() = delete; ObjectLibrary() = default;
~ObjectLibrary() = delete; ~ObjectLibrary() = default;
static void Clear(); void Clear();
static ObjectRef<Type> Get(const std::string& name); std::shared_ptr<Type> Get(const std::string& name);
static bool Has(const std::string& name); bool Has(const std::string& name);
static void Register(const std::string& name, ObjectRef<Type> object); void Register(const std::string& name, std::shared_ptr<Type> object);
static ObjectRef<Type> Query(const std::string& name); std::shared_ptr<Type> Query(const std::string& name);
static void Unregister(const std::string& name); void Unregister(const std::string& name);
private: private:
static bool Initialize(); std::unordered_map<std::string, std::shared_ptr<Type>> m_library;
static void Uninitialize();
using LibraryMap = std::unordered_map<std::string, ObjectRef<Type>>;
}; };
} }

View File

@ -20,11 +20,11 @@ namespace Nz
template<typename Type> template<typename Type>
void ObjectLibrary<Type>::Clear() 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 * \return Optional reference
* *
* \param name Name of the object * \param name Name of the object
@ -32,9 +32,9 @@ namespace Nz
* \remark Produces a NazaraError if object not found * \remark Produces a NazaraError if object not found
*/ */
template<typename Type> 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) if (!ref)
NazaraError("Object \"" + name + "\" is not present"); NazaraError("Object \"" + name + "\" is not present");
@ -48,58 +48,46 @@ namespace Nz
template<typename Type> template<typename Type>
bool ObjectLibrary<Type>::Has(const std::string& name) 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 name Name of the object
* \param object Object to stock * \param object Object to stock
*/ */
template<typename Type> 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 * \return Optional reference
* *
* \param name Name of the object * \param name Name of the object
*/ */
template<typename Type> 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); auto it = m_library.find(name);
if (it != Type::s_library.end()) if (it != m_library.end())
return it->second; return it->second;
else else
return nullptr; 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 * \param name Name of the object
*/ */
template<typename Type> template<typename Type>
void ObjectLibrary<Type>::Unregister(const std::string& name) void ObjectLibrary<Type>::Unregister(const std::string& name)
{ {
Type::s_library.erase(name); m_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();
} }
} }

View File

@ -8,14 +8,13 @@
#define NAZARA_RESOURCELOADER_HPP #define NAZARA_RESOURCELOADER_HPP
#include <Nazara/Core/Enums.hpp> #include <Nazara/Core/Enums.hpp>
#include <Nazara/Core/ObjectRef.hpp>
#include <Nazara/Core/RefCounted.hpp>
#include <Nazara/Core/Resource.hpp> #include <Nazara/Core/Resource.hpp>
#include <Nazara/Core/ResourceParameters.hpp> #include <Nazara/Core/ResourceParameters.hpp>
#include <filesystem> #include <filesystem>
#include <list> #include <functional>
#include <tuple> #include <memory>
#include <type_traits> #include <type_traits>
#include <vector>
namespace Nz namespace Nz
{ {
@ -29,27 +28,43 @@ namespace Nz
friend Type; friend Type;
public: public:
using ExtensionGetter = bool (*)(const std::string& extension); struct Entry;
using FileLoader = ObjectRef<Type> (*)(const std::filesystem::path& filePath, const Parameters& parameters); using ExtensionSupport = std::function<bool(const std::string_view& extension)>;
using MemoryLoader = ObjectRef<Type> (*)(const void* data, std::size_t size, const Parameters& parameters); using FileLoader = std::function<std::shared_ptr<Type>(const std::filesystem::path& filePath, const Parameters& parameters)>;
using StreamChecker = Ternary (*)(Stream& stream, const Parameters& parameters); using MemoryLoader = std::function<std::shared_ptr<Type>(const void* data, std::size_t size, const Parameters& parameters)>;
using StreamLoader = ObjectRef<Type> (*)(Stream& stream, 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() = default;
~ResourceLoader() = delete; 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()); bool IsExtensionSupported(const std::string_view& extension) const;
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());
static void RegisterLoader(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;
static void UnregisterLoader(ExtensionGetter extensionGetter, StreamChecker checkFunc, StreamLoader streamLoader, FileLoader fileLoader = nullptr, MemoryLoader memoryLoader = nullptr); 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: private:
using Loader = std::tuple<ExtensionGetter, StreamChecker, StreamLoader, FileLoader, MemoryLoader>; std::vector<std::unique_ptr<Entry>> m_loaders;
using LoaderList = std::list<Loader>;
}; };
} }

View File

@ -18,20 +18,29 @@ namespace Nz
* \brief Core class that represents a loader of resources * \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 * \brief Checks whether the extension of the file is supported
* \return true if supported * \return true if supported
* *
* \param extension Extension of the file * \param extension Extension of the file (ex: "png")
*/ */
template<typename Type, typename Parameters> 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; return true;
} }
@ -54,7 +63,7 @@ namespace Nz
* \remark Produces a NazaraError if all loaders failed or no loader was found * \remark Produces a NazaraError if all loaders failed or no loader was found
*/ */
template<typename Type, typename Parameters> 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"); NazaraAssert(parameters.IsValid(), "Invalid parameters");
@ -71,17 +80,14 @@ namespace Nz
File file(filePath.generic_u8string()); // Open only if needed File file(filePath.generic_u8string()); // Open only if needed
bool found = false; bool found = false;
for (Loader& loader : Type::s_loaders) for (auto& loaderPtr : m_loaders)
{ {
ExtensionGetter isExtensionSupported = std::get<0>(loader); const Entry& loader = *loaderPtr;
if (!isExtensionSupported || !isExtensionSupported(ext))
if (loader.extensionSupport && !loader.extensionSupport(ext))
continue; continue;
StreamChecker checkFunc = std::get<1>(loader); if (loader.streamChecker && !file.IsOpen())
StreamLoader streamLoader = std::get<2>(loader);
FileLoader fileLoader = std::get<3>(loader);
if (checkFunc && !file.IsOpen())
{ {
if (!file.Open(OpenMode_ReadOnly)) if (!file.Open(OpenMode_ReadOnly))
{ {
@ -90,26 +96,26 @@ namespace Nz
} }
} }
Ternary recognized = Ternary_Unknown; Ternary recognized = Ternary::Unknown;
if (fileLoader) if (loader.fileLoader)
{ {
if (checkFunc) if (loader.streamChecker)
{ {
file.SetCursorPos(0); file.SetCursorPos(0);
recognized = checkFunc(file, parameters); recognized = loader.streamChecker(file, parameters);
if (recognized == Ternary_False) if (recognized == Ternary::False)
continue; continue;
else else
found = true; found = true;
} }
else else
{ {
recognized = Ternary_Unknown; recognized = Ternary::Unknown;
found = true; found = true;
} }
ObjectRef<Type> resource = fileLoader(filePath, parameters); std::shared_ptr<Type> resource = loader.fileLoader(filePath, parameters);
if (resource) if (resource)
{ {
resource->SetFilePath(filePath); resource->SetFilePath(filePath);
@ -118,17 +124,19 @@ namespace Nz
} }
else else
{ {
assert(loader.streamChecker);
file.SetCursorPos(0); file.SetCursorPos(0);
recognized = checkFunc(file, parameters); recognized = loader.streamChecker(file, parameters);
if (recognized == Ternary_False) if (recognized == Ternary::False)
continue; continue;
else if (recognized == Ternary_True) else if (recognized == Ternary::True)
found = true; found = true;
file.SetCursorPos(0); file.SetCursorPos(0);
ObjectRef<Type> resource = streamLoader(file, parameters); std::shared_ptr<Type> resource = loader.streamLoader(file, parameters);
if (resource) if (resource)
{ {
resource->SetFilePath(filePath); resource->SetFilePath(filePath);
@ -136,7 +144,7 @@ namespace Nz
} }
} }
if (recognized == Ternary_True) if (recognized == Ternary::True)
NazaraWarning("Loader failed"); NazaraWarning("Loader failed");
} }
@ -164,7 +172,7 @@ namespace Nz
* \remark Produces a NazaraError if all loaders failed or no loader was found * \remark Produces a NazaraError if all loaders failed or no loader was found
*/ */
template<typename Type, typename Parameters> 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(data, "Invalid data pointer");
NazaraAssert(size, "No data to load"); NazaraAssert(size, "No data to load");
@ -173,32 +181,30 @@ namespace Nz
MemoryView stream(data, size); MemoryView stream(data, size);
bool found = false; bool found = false;
for (Loader& loader : Type::s_loaders) for (auto& loaderPtr : m_loaders)
{ {
StreamChecker checkFunc = std::get<1>(loader); const Entry& loader = *loaderPtr;
StreamLoader streamLoader = std::get<2>(loader);
MemoryLoader memoryLoader = std::get<4>(loader);
Ternary recognized = Ternary_Unknown; Ternary recognized = Ternary::Unknown;
if (memoryLoader) if (loader.memoryLoader)
{ {
if (checkFunc) if (loader.streamChecker)
{ {
stream.SetCursorPos(0); stream.SetCursorPos(0);
recognized = checkFunc(stream, parameters); recognized = loader.streamChecker(stream, parameters);
if (recognized == Ternary_False) if (recognized == Ternary::False)
continue; continue;
else else
found = true; found = true;
} }
else else
{ {
recognized = Ternary_Unknown; recognized = Ternary::Unknown;
found = true; found = true;
} }
ObjectRef<Type> resource = memoryLoader(data, size, parameters); std::shared_ptr<Type> resource = loader.memoryLoader(data, size, parameters);
if (resource) if (resource)
return resource; return resource;
} }
@ -206,20 +212,20 @@ namespace Nz
{ {
stream.SetCursorPos(0); stream.SetCursorPos(0);
recognized = checkFunc(stream, parameters); recognized = loader.streamChecker(stream, parameters);
if (recognized == Ternary_False) if (recognized == Ternary::False)
continue; continue;
else if (recognized == Ternary_True) else if (recognized == Ternary::True)
found = true; found = true;
stream.SetCursorPos(0); stream.SetCursorPos(0);
ObjectRef<Type> resource = streamLoader(stream, parameters); std::shared_ptr<Type> resource = loader.streamLoader(stream, parameters);
if (resource) if (resource)
return resource; return resource;
} }
if (recognized == Ternary_True) if (recognized == Ternary::True)
NazaraWarning("Loader failed"); NazaraWarning("Loader failed");
} }
@ -246,36 +252,35 @@ namespace Nz
* \remark Produces a NazaraError if all loaders failed or no loader was found * \remark Produces a NazaraError if all loaders failed or no loader was found
*/ */
template<typename Type, typename Parameters> 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(stream.GetCursorPos() < stream.GetSize(), "No data to load");
NazaraAssert(parameters.IsValid(), "Invalid parameters"); NazaraAssert(parameters.IsValid(), "Invalid parameters");
UInt64 streamPos = stream.GetCursorPos(); UInt64 streamPos = stream.GetCursorPos();
bool found = false; bool found = false;
for (Loader& loader : Type::s_loaders) for (auto& loaderPtr : m_loaders)
{ {
StreamChecker checkFunc = std::get<1>(loader); const Entry& loader = *loaderPtr;
StreamLoader streamLoader = std::get<2>(loader);
stream.SetCursorPos(streamPos); stream.SetCursorPos(streamPos);
// Does the loader support these data ? // Does the loader support these data ?
Ternary recognized = checkFunc(stream, parameters); Ternary recognized = loader.streamChecker(stream, parameters);
if (recognized == Ternary_False) if (recognized == Ternary::False)
continue; continue;
else if (recognized == Ternary_True) else if (recognized == Ternary::True)
found = true; found = true;
// We move the stream to its old position // We move the stream to its old position
stream.SetCursorPos(streamPos); stream.SetCursorPos(streamPos);
// Load of the resource // Load of the resource
ObjectRef<Type> resource = streamLoader(stream, parameters); std::shared_ptr<Type> resource = loader.streamLoader(stream, parameters);
if (resource) if (resource)
return resource; return resource;
if (recognized == Ternary_True) if (recognized == Ternary::True)
NazaraWarning("Loader failed"); NazaraWarning("Loader failed");
} }
@ -289,35 +294,35 @@ namespace Nz
/*! /*!
* \brief Registers the loader * \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 loader A collection of loader callbacks that will be registered
* \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 * \seealso UnregisterLoader
* \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
*/ */
template<typename Type, typename Parameters> 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(loader.streamChecker || !loader.streamLoader, "StreamLoader present without StreamChecker");
NazaraAssert(fileLoader || memoryLoader || streamLoader, "A loader function is mandatory"); 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 * \brief Unregisters the loader
* *
* \param extensionGetter A function to test whether the extension (as a string) is supported by this loader * \param loader A pointer to a loader returned by RegisterLoad
* \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 * \seealso RegisterLoader
* \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
*/ */
template<typename Type, typename Parameters> 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);
} }
} }

View File

@ -7,9 +7,9 @@
#ifndef NAZARA_RESOURCEMANAGER_HPP #ifndef NAZARA_RESOURCEMANAGER_HPP
#define NAZARA_RESOURCEMANAGER_HPP #define NAZARA_RESOURCEMANAGER_HPP
#include <Nazara/Core/ObjectRef.hpp> #include <Nazara/Core/ResourceLoader.hpp>
#include <Nazara/Core/ResourceParameters.hpp>
#include <filesystem> #include <filesystem>
#include <memory>
#include <unordered_map> #include <unordered_map>
namespace Nz namespace Nz
@ -17,26 +17,27 @@ namespace Nz
template<typename Type, typename Parameters> template<typename Type, typename Parameters>
class ResourceManager class ResourceManager
{ {
friend Type;
public: public:
ResourceManager() = delete; using Loader = ResourceLoader<Type, Parameters>;
~ResourceManager() = delete;
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); void Clear();
static const Parameters& GetDefaultParameters();
static void Purge(); std::shared_ptr<Type> Get(const std::filesystem::path& filePath);
static void Register(const std::filesystem::path& filePath, ObjectRef<Type> resource); const Parameters& GetDefaultParameters();
static void SetDefaultParameters(const Parameters& params);
static void Unregister(const std::filesystem::path& filePath); 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: private:
static bool Initialize();
static void Uninitialize();
// https://stackoverflow.com/questions/51065244/is-there-no-standard-hash-for-stdfilesystempath // https://stackoverflow.com/questions/51065244/is-there-no-standard-hash-for-stdfilesystempath
struct PathHash struct PathHash
{ {
@ -46,8 +47,9 @@ namespace Nz
} }
}; };
using ManagerMap = std::unordered_map<std::filesystem::path, ObjectRef<Type>, PathHash>; std::unordered_map<std::filesystem::path, std::shared_ptr<Type>, PathHash> m_resources;
using ManagerParams = Parameters; Loader& m_loader;
Parameters m_defaultParameters;
}; };
} }

View File

@ -15,13 +15,23 @@ namespace Nz
* \brief Core class that represents a resource manager * \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 * \brief Clears the content of the manager
*/ */
template<typename Type, typename Parameters> template<typename Type, typename Parameters>
void ResourceManager<Type, Parameters>::Clear() 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 * \param filePath Path to the asset that will be loaded
*/ */
template<typename Type, typename Parameters> 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); std::filesystem::path absolutePath = std::filesystem::canonical(filePath);
auto it = Type::s_managerMap.find(absolutePath); auto it = m_resources.find(absolutePath);
if (it == Type::s_managerMap.end()) if (it == m_resources.end())
{ {
ObjectRef<Type> resource = Type::LoadFromFile(absolutePath, GetDefaultParameters()); std::shared_ptr<Type> resource = m_loader.LoadFromFile(absolutePath, GetDefaultParameters());
if (!resource) if (!resource)
{ {
NazaraError("Failed to load resource from file: " + absolutePath.generic_u8string()); 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()); 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; return it->second;
@ -59,27 +69,7 @@ namespace Nz
template<typename Type, typename Parameters> template<typename Type, typename Parameters>
const Parameters& ResourceManager<Type, Parameters>::GetDefaultParameters() const Parameters& ResourceManager<Type, Parameters>::GetDefaultParameters()
{ {
return Type::s_managerParameters; return m_defaultParameters;
}
/*!
* \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;
}
} }
/*! /*!
@ -89,11 +79,11 @@ namespace Nz
* \param resource Object to associate with * \param resource Object to associate with
*/ */
template<typename Type, typename Parameters> 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); 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 * \param params Default parameters for loading from file
*/ */
template<typename Type, typename Parameters> 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); std::filesystem::path absolutePath = std::filesystem::canonical(filePath);
Type::s_managerMap.erase(absolutePath); m_resources.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();
} }
} }

View File

@ -84,9 +84,9 @@ Ternary CheckAnimation(Stream& /*stream*/, const AnimationParams& parameters)
{ {
bool skip; bool skip;
if (parameters.custom.GetBooleanParameter("SkipAssimpLoader", &skip) && 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) AnimationRef LoadAnimation(Stream& stream, const AnimationParams& parameters)
@ -179,9 +179,9 @@ Ternary CheckMesh(Stream& /*stream*/, const MeshParams& parameters)
{ {
bool skip; bool skip;
if (parameters.custom.GetBooleanParameter("SkipAssimpLoader", &skip) && 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) MeshRef LoadMesh(Stream& stream, const MeshParams& parameters)

View File

@ -245,10 +245,10 @@ namespace Nz
if (file) if (file)
{ {
sf_close(file); sf_close(file);
return Ternary_True; return Ternary::True;
} }
else else
return Ternary_False; return Ternary::False;
} }
SoundStreamRef LoadSoundStreamFile(const std::filesystem::path& filePath, const SoundStreamParams& parameters) SoundStreamRef LoadSoundStreamFile(const std::filesystem::path& filePath, const SoundStreamParams& parameters)
@ -301,10 +301,10 @@ namespace Nz
if (file) if (file)
{ {
sf_close(file); sf_close(file);
return Ternary_True; return Ternary::True;
} }
else else
return Ternary_False; return Ternary::False;
} }
SoundBufferRef LoadSoundBuffer(Stream& stream, const SoundBufferParams& parameters) SoundBufferRef LoadSoundBuffer(Stream& stream, const SoundBufferParams& parameters)

View File

@ -27,7 +27,7 @@ namespace Nz
{ {
bool skip; bool skip;
if (parameters.custom.GetBooleanParameter("SkipNativeDDSLoader", &skip) && skip) if (parameters.custom.GetBooleanParameter("SkipNativeDDSLoader", &skip) && skip)
return Ternary_False; return Ternary::False;
ByteStream byteStream(&stream); ByteStream byteStream(&stream);
byteStream.SetDataEndianness(Endianness_LittleEndian); byteStream.SetDataEndianness(Endianness_LittleEndian);
@ -35,7 +35,7 @@ namespace Nz
UInt32 magic; UInt32 magic;
byteStream >> 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) static ImageRef Load(Stream& stream, const ImageParams& parameters)

View File

@ -398,15 +398,15 @@ namespace Nz
{ {
bool skip; bool skip;
if (parameters.custom.GetBooleanParameter("SkipNativeFreeTypeLoader", &skip) && skip) if (parameters.custom.GetBooleanParameter("SkipNativeFreeTypeLoader", &skip) && skip)
return Ternary_False; return Ternary::False;
FreeTypeStream face; FreeTypeStream face;
face.SetStream(stream); face.SetStream(stream);
if (face.Check()) if (face.Check())
return Ternary_True; return Ternary::True;
else else
return Ternary_False; return Ternary::False;
} }
FontRef LoadFile(const std::filesystem::path& filePath, const FontParams& parameters) FontRef LoadFile(const std::filesystem::path& filePath, const FontParams& parameters)

View File

@ -29,7 +29,7 @@ namespace Nz
{ {
bool skip; bool skip;
if (parameters.custom.GetBooleanParameter("SkipNativeMD2Loader", &skip) && skip) if (parameters.custom.GetBooleanParameter("SkipNativeMD2Loader", &skip) && skip)
return Ternary_False; return Ternary::False;
UInt32 magic[2]; UInt32 magic[2];
if (stream.Read(&magic[0], 2*sizeof(UInt32)) == 2*sizeof(UInt32)) if (stream.Read(&magic[0], 2*sizeof(UInt32)) == 2*sizeof(UInt32))
@ -40,10 +40,10 @@ namespace Nz
#endif #endif
if (magic[0] == md2Ident && magic[1] == 8) 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) MeshRef Load(Stream& stream, const MeshParams& parameters)

View File

@ -21,7 +21,7 @@ namespace Nz
{ {
bool skip; bool skip;
if (parameters.custom.GetBooleanParameter("SkipNativeMD5AnimLoader", &skip) && skip) if (parameters.custom.GetBooleanParameter("SkipNativeMD5AnimLoader", &skip) && skip)
return Ternary_False; return Ternary::False;
MD5AnimParser parser(stream); MD5AnimParser parser(stream);
return parser.Check(); return parser.Check();

View File

@ -37,11 +37,11 @@ namespace Nz
if (std::sscanf(&m_currentLine[0], " MD5Version %u", &version) == 1) if (std::sscanf(&m_currentLine[0], " MD5Version %u", &version) == 1)
{ {
if (version == 10) if (version == 10)
return Ternary_True; return Ternary::True;
} }
} }
return Ternary_False; return Ternary::False;
} }
UInt32 MD5AnimParser::GetAnimatedComponentCount() const UInt32 MD5AnimParser::GetAnimatedComponentCount() const

View File

@ -29,7 +29,7 @@ namespace Nz
{ {
bool skip; bool skip;
if (parameters.custom.GetBooleanParameter("SkipNativeMD5MeshLoader", &skip) && skip) if (parameters.custom.GetBooleanParameter("SkipNativeMD5MeshLoader", &skip) && skip)
return Ternary_False; return Ternary::False;
MD5MeshParser parser(stream); MD5MeshParser parser(stream);
return parser.Check(); return parser.Check();

View File

@ -37,11 +37,11 @@ namespace Nz
if (std::sscanf(&m_currentLine[0], " MD5Version %u", &version) == 1) if (std::sscanf(&m_currentLine[0], " MD5Version %u", &version) == 1)
{ {
if (version == 10) if (version == 10)
return Ternary_True; return Ternary::True;
} }
} }
return Ternary_False; return Ternary::False;
} }
const MD5MeshParser::Joint* MD5MeshParser::GetJoints() const const MD5MeshParser::Joint* MD5MeshParser::GetJoints() const

View File

@ -33,13 +33,13 @@ namespace Nz
bool skip; bool skip;
if (parameters.custom.GetBooleanParameter("SkipNativeOBJLoader", &skip) && skip) if (parameters.custom.GetBooleanParameter("SkipNativeOBJLoader", &skip) && skip)
return Ternary_False; return Ternary::False;
OBJParser parser; OBJParser parser;
if (!parser.Check(stream)) 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) bool ParseMTL(Mesh* mesh, const std::filesystem::path& filePath, const std::string* materials, const OBJParser::Mesh* meshes, std::size_t meshCount)

View File

@ -49,16 +49,16 @@ namespace Nz
{ {
bool skip; bool skip;
if (parameters.custom.GetBooleanParameter("SkipNativePCXLoader", &skip) && skip) if (parameters.custom.GetBooleanParameter("SkipNativePCXLoader", &skip) && skip)
return Ternary_False; return Ternary::False;
UInt8 manufacturer; UInt8 manufacturer;
if (stream.Read(&manufacturer, 1) == 1) if (stream.Read(&manufacturer, 1) == 1)
{ {
if (manufacturer == 0x0a) if (manufacturer == 0x0a)
return Ternary_True; return Ternary::True;
} }
return Ternary_False; return Ternary::False;
} }
ImageRef Load(Stream& stream, const ImageParams& parameters) ImageRef Load(Stream& stream, const ImageParams& parameters)

View File

@ -46,13 +46,13 @@ namespace Nz
{ {
bool skip; bool skip;
if (parameters.custom.GetBooleanParameter("SkipNativeSTBLoader", &skip) && skip) if (parameters.custom.GetBooleanParameter("SkipNativeSTBLoader", &skip) && skip)
return Ternary_False; return Ternary::False;
int width, height, bpp; int width, height, bpp;
if (stbi_info_from_callbacks(&callbacks, &stream, &width, &height, &bpp)) if (stbi_info_from_callbacks(&callbacks, &stream, &width, &height, &bpp))
return Ternary_True; return Ternary::True;
else else
return Ternary_False; return Ternary::False;
} }
ImageRef Load(Stream& stream, const ImageParams& parameters) ImageRef Load(Stream& stream, const ImageParams& parameters)

View File

@ -9,7 +9,7 @@ SCENARIO("SoundBuffer", "[AUDIO][SOUNDBUFFER]")
{ {
WHEN("We load our sound") 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()); REQUIRE(soundBuffer.IsValid());
THEN("We can ask the informations of the file") THEN("We can ask the informations of the file")