// Copyright (C) 2023 Jérôme "Lynix" Leclercq (lynix680@gmail.com) // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp #include #include #include #include namespace Nz { namespace Detail { template struct ResourceParameterHasMerge : std::false_type {}; template struct ResourceParameterHasMerge().Merge(std::declval()))>> : std::true_type {}; } inline AppFilesystemComponent::AppFilesystemComponent(ApplicationBase& app) : ApplicationComponent(app) { RegisterResourceTypes(); } template const typename T::Params* AppFilesystemComponent::GetDefaultResourceParameters() const { std::size_t resourceIndex = ResourceRegistry::GetResourceId(); if (resourceIndex >= m_defaultParameters.size()) return nullptr; return static_cast(m_defaultParameters[resourceIndex].get()); } template std::shared_ptr AppFilesystemComponent::Load(std::string_view assetPath) { return Load(assetPath, typename T::Params{}); } template std::shared_ptr AppFilesystemComponent::Load(std::string_view assetPath, typename T::Params params) { if constexpr (Detail::ResourceParameterHasMerge::value) { if (const auto* defaultParams = GetDefaultResourceParameters()) params.Merge(*defaultParams); } return LoadImpl(assetPath, params); } template std::shared_ptr AppFilesystemComponent::Open(std::string_view assetPath) { return Open(assetPath, typename T::Params{}); } template std::shared_ptr AppFilesystemComponent::Open(std::string_view assetPath, typename T::Params params) { if constexpr (Detail::ResourceParameterHasMerge::value) { if (const auto* defaultParams = GetDefaultResourceParameters()) params.Merge(*defaultParams); } return OpenImpl(assetPath, params); } template void AppFilesystemComponent::SetDefaultResourceParameters(typename T::Params params) { std::size_t resourceIndex = ResourceRegistry::GetResourceId(); if (resourceIndex >= m_defaultParameters.size()) m_defaultParameters.resize(resourceIndex + 1); m_defaultParameters[resourceIndex] = std::make_unique(std::move(params)); } inline void AppFilesystemComponent::RegisterResourceTypes() { // TODO: Switch to hash-based approach like entt? if (ResourceRegistry::GetResourceId() != 0) throw std::runtime_error("Font has wrong resource index, please initialize AppFilesystemComponent before using ResourceRegistry"); if (ResourceRegistry::GetResourceId() != 1) throw std::runtime_error("Image has wrong resource index, please initialize AppFilesystemComponent before using ResourceRegistry"); if (ResourceRegistry::GetResourceId() != 2) throw std::runtime_error("ImageStream has wrong resource index, please initialize AppFilesystemComponent before using ResourceRegistry"); if (ResourceRegistry::GetResourceId() != 3) throw std::runtime_error("Material has wrong resource index, please initialize AppFilesystemComponent before using ResourceRegistry"); if (ResourceRegistry::GetResourceId() != 4) throw std::runtime_error("MaterialInstance has wrong resource index, please initialize AppFilesystemComponent before using ResourceRegistry"); if (ResourceRegistry::GetResourceId() != 5) throw std::runtime_error("Mesh has wrong resource index, please initialize AppFilesystemComponent before using ResourceRegistry"); if (ResourceRegistry::GetResourceId() != 6) throw std::runtime_error("SoundBuffer has wrong resource index, please initialize AppFilesystemComponent before using ResourceRegistry"); if (ResourceRegistry::GetResourceId() != 7) throw std::runtime_error("SoundStream has wrong resource index, please initialize AppFilesystemComponent before using ResourceRegistry"); if (ResourceRegistry::GetResourceId() != 8) throw std::runtime_error("Texture has wrong resource index, please initialize AppFilesystemComponent before using ResourceRegistry"); } template std::shared_ptr AppFilesystemComponent::LoadImpl(std::string_view assetPath, const typename T::Params& params) { std::shared_ptr resource; if (!m_rootDirectory) return resource; auto callback = [&](const VirtualDirectory::Entry& entry) { return std::visit([&](auto&& arg) { using Param = std::decay_t; if constexpr (std::is_base_of_v) { NazaraError(std::string(assetPath) + " is a directory"); return false; } else if constexpr (std::is_same_v) { resource = T::LoadFromStream(*arg.stream, params); return true; } else static_assert(AlwaysFalse(), "unhandled case"); }, entry); }; m_rootDirectory->GetEntry(assetPath, callback); return resource; } template std::shared_ptr AppFilesystemComponent::OpenImpl(std::string_view assetPath, const typename T::Params& params) { std::shared_ptr resource; if (!m_rootDirectory) return resource; auto callback = [&](const VirtualDirectory::Entry& entry) { return std::visit([&](auto&& arg) { using Param = std::decay_t; if constexpr (std::is_base_of_v) { NazaraError(std::string(assetPath) + " is a directory"); return false; } else if constexpr (std::is_same_v) { resource = T::OpenFromStream(*arg.stream, params); return true; } else static_assert(AlwaysFalse(), "unhandled case"); }, entry); }; m_rootDirectory->GetEntry(assetPath, callback); return resource; } } #include