Refactor the way resources are loaded (#191)

* WIP

* WIP

* Font works

* WIP: Only Music remains

* Looks like it's working

* Fix oopsie

* Core/ObjectRef: Add cast functions

* Update ChangeLog.md

* Audio/SoundStream: Make sound stream thread-safe
This commit is contained in:
Jérôme Leclercq
2018-10-28 01:53:11 +02:00
committed by GitHub
parent fa7cbc21e5
commit ed46c87781
64 changed files with 1058 additions and 1071 deletions

View File

@@ -68,6 +68,10 @@ namespace Nz
template<typename T> bool operator>=(const T& lhs, const ObjectRef<T>& rhs);
template<typename T> bool operator>=(const ObjectRef<T>& lhs, const T& rhs);
template<typename T, typename U> ObjectRef<T> ConstRefCast(const ObjectRef<U>& ref);
template<typename T, typename U> ObjectRef<T> DynamicRefCast(const ObjectRef<U>& ref);
template<typename T, typename U> ObjectRef<T> ReinterpretRefCast(const ObjectRef<U>& ref);
template<typename T, typename U> ObjectRef<T> StaticRefCast(const ObjectRef<U>& ref);
template<typename T> struct PointedType<ObjectRef<T>> { using type = T; };
template<typename T> struct PointedType<ObjectRef<T> const> { using type = T; };

View File

@@ -480,6 +480,60 @@ namespace Nz
{
return !(lhs < rhs);
}
/*!
* \brief Casts an ObjectRef from one type to another using static_cast
* \return Reference to the casted object
*
* \param ref The reference to convert
*
* \remark It is an undefined behavior to cast between incompatible types
*/
template<typename T, typename U>
ObjectRef<T> ConstRefCast(const ObjectRef<U>& ref)
{
return ObjectRef<T>(const_cast<T*>(ref.Get()));
}
/*!
* \brief Casts an ObjectRef from one type to another using static_cast
* \return Reference to the casted object
*
* \param ref The reference to convert
*/
template<typename T, typename U>
ObjectRef<T> DynamicRefCast(const ObjectRef<U>& ref)
{
return ObjectRef<T>(dynamic_cast<T*>(ref.Get()));
}
/*!
* \brief Casts an ObjectRef from one type to another using static_cast
* \return Reference to the casted object
*
* \param ref The reference to convert
*
* \remark It is an undefined behavior to cast between incompatible types
*/
template<typename T, typename U>
ObjectRef<T> ReinterpretRefCast(const ObjectRef<U>& ref)
{
return ObjectRef<T>(static_cast<T*>(ref.Get()));
}
/*!
* \brief Casts an ObjectRef from one type to another using static_cast
* \return Reference to the casted object
*
* \param ref The reference to convert
*
* \remark It is an undefined behavior to cast between incompatible types
*/
template<typename T, typename U>
ObjectRef<T> StaticRefCast(const ObjectRef<U>& ref)
{
return ObjectRef<T>(static_cast<T*>(ref.Get()));
}
}
namespace std
@@ -504,3 +558,4 @@ namespace std
}
#include <Nazara/Core/DebugOff.hpp>
#include "ObjectRef.hpp"

View File

@@ -8,6 +8,8 @@
#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 <Nazara/Core/String.hpp>
@@ -28,19 +30,19 @@ namespace Nz
public:
using ExtensionGetter = bool (*)(const String& extension);
using FileLoader = bool (*)(Type* resource, const String& filePath, const Parameters& parameters);
using MemoryLoader = bool (*)(Type* resource, const void* data, std::size_t size, const Parameters& parameters);
using FileLoader = ObjectRef<Type> (*)(const String& 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 = bool (*)(Type* resource, Stream& stream, const Parameters& parameters);
using StreamLoader = ObjectRef<Type> (*)(Stream& stream, const Parameters& parameters);
ResourceLoader() = delete;
~ResourceLoader() = delete;
static bool IsExtensionSupported(const String& extension);
static bool LoadFromFile(Type* resource, const String& filePath, const Parameters& parameters = Parameters());
static bool LoadFromMemory(Type* resource, const void* data, std::size_t size, const Parameters& parameters = Parameters());
static bool LoadFromStream(Type* resource, Stream& stream, const Parameters& parameters = Parameters());
static ObjectRef<Type> LoadFromFile(const String& 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());
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);

View File

@@ -53,9 +53,8 @@ namespace Nz
* \remark Produces a NazaraError if all loaders failed or no loader was found
*/
template<typename Type, typename Parameters>
bool ResourceLoader<Type, Parameters>::LoadFromFile(Type* resource, const String& filePath, const Parameters& parameters)
ObjectRef<Type> ResourceLoader<Type, Parameters>::LoadFromFile(const String& filePath, const Parameters& parameters)
{
NazaraAssert(resource, "Invalid resource");
NazaraAssert(parameters.IsValid(), "Invalid parameters");
String path = File::NormalizePath(filePath);
@@ -63,7 +62,7 @@ namespace Nz
if (ext.IsEmpty())
{
NazaraError("Failed to get file extension from \"" + filePath + '"');
return false;
return nullptr;
}
File file(path); // Open only if needed
@@ -84,7 +83,7 @@ namespace Nz
if (!file.Open(OpenMode_ReadOnly))
{
NazaraError("Failed to load file: unable to open \"" + filePath + '"');
return false;
return nullptr;
}
}
@@ -107,10 +106,11 @@ namespace Nz
found = true;
}
if (fileLoader(resource, filePath, parameters))
ObjectRef<Type> resource = fileLoader(filePath, parameters);
if (resource)
{
resource->SetFilePath(filePath);
return true;
return resource;
}
}
else
@@ -125,10 +125,11 @@ namespace Nz
file.SetCursorPos(0);
if (streamLoader(resource, file, parameters))
ObjectRef<Type> resource = streamLoader(file, parameters);
if (resource)
{
resource->SetFilePath(filePath);
return true;
return resource;
}
}
@@ -141,7 +142,7 @@ namespace Nz
else
NazaraError("Failed to load file: no loader found for extension \"" + ext + '"');
return false;
return nullptr;
}
/*!
@@ -160,9 +161,8 @@ namespace Nz
* \remark Produces a NazaraError if all loaders failed or no loader was found
*/
template<typename Type, typename Parameters>
bool ResourceLoader<Type, Parameters>::LoadFromMemory(Type* resource, const void* data, std::size_t size, const Parameters& parameters)
ObjectRef<Type> ResourceLoader<Type, Parameters>::LoadFromMemory(const void* data, std::size_t size, const Parameters& parameters)
{
NazaraAssert(resource, "Invalid resource");
NazaraAssert(data, "Invalid data pointer");
NazaraAssert(size, "No data to load");
NazaraAssert(parameters.IsValid(), "Invalid parameters");
@@ -195,8 +195,9 @@ namespace Nz
found = true;
}
if (memoryLoader(resource, data, size, parameters))
return true;
ObjectRef<Type> resource = memoryLoader(data, size, parameters);
if (resource)
return resource;
}
else
{
@@ -210,8 +211,9 @@ namespace Nz
stream.SetCursorPos(0);
if (streamLoader(resource, stream, parameters))
return true;
ObjectRef<Type> resource = streamLoader(stream, parameters);
if (resource)
return resource;
}
if (recognized == Ternary_True)
@@ -223,7 +225,7 @@ namespace Nz
else
NazaraError("Failed to load file: no loader found");
return false;
return nullptr;
}
/*!
@@ -241,9 +243,8 @@ namespace Nz
* \remark Produces a NazaraError if all loaders failed or no loader was found
*/
template<typename Type, typename Parameters>
bool ResourceLoader<Type, Parameters>::LoadFromStream(Type* resource, Stream& stream, const Parameters& parameters)
ObjectRef<Type> ResourceLoader<Type, Parameters>::LoadFromStream(Stream& stream, const Parameters& parameters)
{
NazaraAssert(resource, "Invalid resource");
NazaraAssert(stream.GetCursorPos() < stream.GetSize(), "No data to load");
NazaraAssert(parameters.IsValid(), "Invalid parameters");
@@ -267,8 +268,9 @@ namespace Nz
stream.SetCursorPos(streamPos);
// Load of the resource
if (streamLoader(resource, stream, parameters))
return true;
ObjectRef<Type> resource = streamLoader(stream, parameters);
if (resource)
return resource;
if (recognized == Ternary_True)
NazaraWarning("Loader failed");
@@ -279,7 +281,7 @@ namespace Nz
else
NazaraError("Failed to load file: no loader found");
return false;
return nullptr;
}
/*!

View File

@@ -37,14 +37,8 @@ namespace Nz
auto it = Type::s_managerMap.find(absolutePath);
if (it == Type::s_managerMap.end())
{
ObjectRef<Type> resource = Type::New();
ObjectRef<Type> resource = Type::LoadFromFile(absolutePath, GetDefaultParameters());
if (!resource)
{
NazaraError("Failed to create resource");
return ObjectRef<Type>();
}
if (!resource->LoadFromFile(absolutePath, GetDefaultParameters()))
{
NazaraError("Failed to load resource from file: " + absolutePath);
return ObjectRef<Type>();