Rework ResourceLoader, ResourceManager and ObjectLibrary
They're no longer static
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user