// 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 #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::GetOrLoad(std::string_view assetPath) { return GetOrLoad(assetPath, typename T::Params{}); } template std::shared_ptr AppFilesystemComponent::GetOrLoad(std::string_view assetPath, typename T::Params params) { if constexpr (Detail::ResourceParameterHasMerge::value) { if (const auto* defaultParams = GetDefaultResourceParameters()) params.Merge(*defaultParams); } return GetOrLoadImpl(assetPath, params); } inline const VirtualDirectoryPtr& AppFilesystemComponent::Mount(std::string_view name, std::filesystem::path filepath) { return Mount(name, std::make_shared(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(); return m_rootDirectory->StoreDirectory(name, std::move(directory)).directory; } 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::GetOrLoadImpl(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::LoadFromMemory(arg.data, arg.size, params); return true; } else if constexpr (std::is_same_v) { resource = T::LoadFromMemory(&arg.data[0], arg.data.size(), params); return true; } else if constexpr (std::is_same_v) { resource = T::LoadFromFile(arg.filePath, params); return true; } else static_assert(AlwaysFalse(), "unhandled case"); }, entry); }; m_rootDirectory->GetEntry(assetPath, callback); return resource; } } #include