Core/AppFilesystemComponent: Add support for default resource parameters
This commit is contained in:
@@ -4,68 +4,153 @@
|
||||
|
||||
#include <Nazara/Core/AppFilesystemComponent.hpp>
|
||||
#include <Nazara/Core/Error.hpp>
|
||||
#include <Nazara/Core/ResourceRegistry.hpp>
|
||||
#include <stdexcept>
|
||||
#include <Nazara/Core/Debug.hpp>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
template<typename T, typename... Args>
|
||||
std::shared_ptr<T> AppFilesystemComponent::GetOrLoad(std::string_view assetPath, Args&&... args)
|
||||
namespace Detail
|
||||
{
|
||||
std::shared_ptr<T> resource;
|
||||
for (const VirtualDirectoryPtr& virtualDir : m_virtualDirectories)
|
||||
{
|
||||
auto callback = [&](const VirtualDirectory::Entry& entry)
|
||||
{
|
||||
return std::visit([&](auto&& arg)
|
||||
{
|
||||
using Param = std::decay_t<decltype(arg)>;
|
||||
if constexpr (std::is_base_of_v<VirtualDirectory::DirectoryEntry, Param>)
|
||||
{
|
||||
NazaraError(std::string(assetPath) + " is a directory");
|
||||
return false;
|
||||
}
|
||||
else if constexpr (std::is_same_v<Param, VirtualDirectory::DataPointerEntry>)
|
||||
{
|
||||
resource = T::LoadFromMemory(arg.data, arg.size, std::forward<Args>(args)...);
|
||||
return true;
|
||||
}
|
||||
else if constexpr (std::is_same_v<Param, VirtualDirectory::FileContentEntry>)
|
||||
{
|
||||
resource = T::LoadFromMemory(&arg.data[0], arg.data.size(), std::forward<Args>(args)...);
|
||||
return true;
|
||||
}
|
||||
else if constexpr (std::is_same_v<Param, VirtualDirectory::PhysicalFileEntry>)
|
||||
{
|
||||
resource = T::LoadFromFile(arg.filePath, std::forward<Args>(args)...);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
static_assert(AlwaysFalse<Param>(), "unhandled case");
|
||||
}, entry);
|
||||
};
|
||||
template<typename, typename = void>
|
||||
struct ResourceParameterHasMerge : std::false_type {};
|
||||
|
||||
if (virtualDir->GetEntry(assetPath, callback) && resource)
|
||||
return resource;
|
||||
template<typename T>
|
||||
struct ResourceParameterHasMerge<T, std::void_t<decltype(std::declval<T>().Merge(std::declval<T>()))>> : std::true_type {};
|
||||
}
|
||||
|
||||
inline AppFilesystemComponent::AppFilesystemComponent(ApplicationBase& app) :
|
||||
ApplicationComponent(app)
|
||||
{
|
||||
RegisterResourceTypes();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
const typename T::Params* AppFilesystemComponent::GetDefaultResourceParameters() const
|
||||
{
|
||||
std::size_t resourceIndex = ResourceRegistry<T>::GetResourceId();
|
||||
if (resourceIndex >= m_defaultParameters.size())
|
||||
return nullptr;
|
||||
|
||||
return static_cast<const typename T::Params*>(m_defaultParameters[resourceIndex].get());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::shared_ptr<T> AppFilesystemComponent::GetOrLoad(std::string_view assetPath)
|
||||
{
|
||||
return GetOrLoad<T>(assetPath, typename T::Params{});
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::shared_ptr<T> AppFilesystemComponent::GetOrLoad(std::string_view assetPath, typename T::Params params)
|
||||
{
|
||||
if constexpr (Detail::ResourceParameterHasMerge<typename T::Params>::value)
|
||||
{
|
||||
if (const auto* defaultParams = GetDefaultResourceParameters<T>())
|
||||
params.Merge(*defaultParams);
|
||||
}
|
||||
|
||||
return GetOrLoadImpl<T>(assetPath, params);
|
||||
}
|
||||
|
||||
inline const VirtualDirectoryPtr& AppFilesystemComponent::Mount(std::string_view name, std::filesystem::path filepath)
|
||||
{
|
||||
return Mount(name, std::make_shared<VirtualDirectory>(std::move(filepath)));
|
||||
}
|
||||
|
||||
inline const VirtualDirectoryPtr& AppFilesystemComponent::Mount(std::string_view name, VirtualDirectoryPtr directory)
|
||||
{
|
||||
if (name.empty())
|
||||
{
|
||||
m_rootDirectory = std::move(directory);
|
||||
return m_rootDirectory;
|
||||
}
|
||||
|
||||
if (!m_rootDirectory)
|
||||
m_rootDirectory = std::make_shared<VirtualDirectory>();
|
||||
|
||||
return m_rootDirectory->StoreDirectory(name, std::move(directory)).directory;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void AppFilesystemComponent::SetDefaultResourceParameters(typename T::Params params)
|
||||
{
|
||||
std::size_t resourceIndex = ResourceRegistry<T>::GetResourceId();
|
||||
if (resourceIndex >= m_defaultParameters.size())
|
||||
m_defaultParameters.resize(resourceIndex + 1);
|
||||
|
||||
m_defaultParameters[resourceIndex] = std::make_unique<typename T::Params>(std::move(params));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::shared_ptr<T> AppFilesystemComponent::GetOrLoadImpl(std::string_view assetPath, const typename T::Params& params)
|
||||
{
|
||||
std::shared_ptr<T> resource;
|
||||
if (!m_rootDirectory)
|
||||
return resource;
|
||||
|
||||
auto callback = [&](const VirtualDirectory::Entry& entry)
|
||||
{
|
||||
return std::visit([&](auto&& arg)
|
||||
{
|
||||
using Param = std::decay_t<decltype(arg)>;
|
||||
if constexpr (std::is_base_of_v<VirtualDirectory::DirectoryEntry, Param>)
|
||||
{
|
||||
NazaraError(std::string(assetPath) + " is a directory");
|
||||
return false;
|
||||
}
|
||||
else if constexpr (std::is_same_v<Param, VirtualDirectory::DataPointerEntry>)
|
||||
{
|
||||
resource = T::LoadFromMemory(arg.data, arg.size, params);
|
||||
return true;
|
||||
}
|
||||
else if constexpr (std::is_same_v<Param, VirtualDirectory::FileContentEntry>)
|
||||
{
|
||||
resource = T::LoadFromMemory(&arg.data[0], arg.data.size(), params);
|
||||
return true;
|
||||
}
|
||||
else if constexpr (std::is_same_v<Param, VirtualDirectory::PhysicalFileEntry>)
|
||||
{
|
||||
resource = T::LoadFromFile(arg.filePath, params);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
static_assert(AlwaysFalse<Param>(), "unhandled case");
|
||||
}, entry);
|
||||
};
|
||||
|
||||
m_rootDirectory->GetEntry(assetPath, callback);
|
||||
return resource;
|
||||
}
|
||||
|
||||
inline const VirtualDirectoryPtr& AppFilesystemComponent::RegisterPath(std::filesystem::path filepath)
|
||||
inline void AppFilesystemComponent::RegisterResourceTypes()
|
||||
{
|
||||
return RegisterVirtualDirectory(std::make_shared<VirtualDirectory>(std::move(filepath)));
|
||||
}
|
||||
if (ResourceRegistry<Font>::GetResourceId() != 0)
|
||||
throw std::runtime_error("Font has wrong resource index, please initialize AppFilesystemComponent before using ResourceRegistry");
|
||||
|
||||
inline const VirtualDirectoryPtr& AppFilesystemComponent::RegisterVirtualDirectory(VirtualDirectoryPtr directory)
|
||||
{
|
||||
return m_virtualDirectories.emplace_back(std::move(directory));
|
||||
}
|
||||
if (ResourceRegistry<Image>::GetResourceId() != 1)
|
||||
throw std::runtime_error("Image has wrong resource index, please initialize AppFilesystemComponent before using ResourceRegistry");
|
||||
|
||||
inline void AppFilesystemComponent::UnregisterVirtualDirectory(const VirtualDirectoryPtr& directory)
|
||||
{
|
||||
auto it = std::find(m_virtualDirectories.begin(), m_virtualDirectories.end(), directory);
|
||||
if (it == m_virtualDirectories.end())
|
||||
m_virtualDirectories.erase(it);
|
||||
if (ResourceRegistry<ImageStream>::GetResourceId() != 2)
|
||||
throw std::runtime_error("ImageStream has wrong resource index, please initialize AppFilesystemComponent before using ResourceRegistry");
|
||||
|
||||
if (ResourceRegistry<Material>::GetResourceId() != 3)
|
||||
throw std::runtime_error("Material has wrong resource index, please initialize AppFilesystemComponent before using ResourceRegistry");
|
||||
|
||||
if (ResourceRegistry<MaterialInstance>::GetResourceId() != 4)
|
||||
throw std::runtime_error("MaterialInstance has wrong resource index, please initialize AppFilesystemComponent before using ResourceRegistry");
|
||||
|
||||
if (ResourceRegistry<Mesh>::GetResourceId() != 5)
|
||||
throw std::runtime_error("Mesh has wrong resource index, please initialize AppFilesystemComponent before using ResourceRegistry");
|
||||
|
||||
if (ResourceRegistry<SoundBuffer>::GetResourceId() != 6)
|
||||
throw std::runtime_error("SoundBuffer has wrong resource index, please initialize AppFilesystemComponent before using ResourceRegistry");
|
||||
|
||||
if (ResourceRegistry<SoundStream>::GetResourceId() != 7)
|
||||
throw std::runtime_error("SoundStream has wrong resource index, please initialize AppFilesystemComponent before using ResourceRegistry");
|
||||
|
||||
if (ResourceRegistry<Texture>::GetResourceId() != 8)
|
||||
throw std::runtime_error("Texture has wrong resource index, please initialize AppFilesystemComponent before using ResourceRegistry");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user