#include "copium/asset/AssetManager.h" #include "copium/sampler/Texture2D.h" #include "copium/util/Common.h" #include "copium/util/MetaFile.h" #include #include namespace Copium { std::vector AssetManager::assetDirs; std::map> AssetManager::assets; std::map AssetManager::pathToAssetCache; std::map AssetManager::nameToAssetCache; std::vector AssetManager::cachedAssetFiles; AssetHandle AssetManager::assetHandle = 1; AssetHandle AssetManager::runtimeAssetHandle = (1 << 31) + 1; void AssetManager::RegisterAssetDir(std::string assetDir) { if (assetDir.back() == '/') assetDir.pop_back(); assetDirs.emplace_back(assetDir); for (std::filesystem::recursive_directory_iterator it(assetDir), end; it != end; ++it) { if (std::filesystem::is_directory(it->path())) continue; std::filesystem::path assetDirPath{assetDir}; cachedAssetFiles.emplace_back(assetDir + "/" + std::filesystem::absolute(it->path()).string().substr(std::filesystem::absolute(assetDirPath).string().size()).c_str()); } UUID uuid{}; CP_INFO(uuid.ToString().c_str()); } void AssetManager::UnregisterAssetDir(std::string assetDir) { if (assetDir.back() == '/') assetDir.pop_back(); for (auto it = assetDirs.begin(); it != assetDirs.end(); ++it) { if (*it == assetDir) { assetDirs.erase(it); return; } } } Asset& AssetManager::GetAsset(AssetHandle handle) { auto it = assets.find(handle); CP_ASSERT(it != assets.end(), "Asset not loaded"); return *it->second.get(); } Asset& AssetManager::LoadAsset(const std::string& assetPath) { CP_DEBUG("Loading Asset: %s", assetPath.c_str()); for (auto& dir : assetDirs) { std::string path = dir + "/" + assetPath; auto it = pathToAssetCache.find(path); if (it != pathToAssetCache.end()) return *assets.find(it->second)->second.get(); std::ifstream file{path}; if (!file.good()) continue; MetaFile metaFile{path}; if (metaFile.HasMetaClass("Texture2D")) { return CreateAsset(metaFile, "Texture2D"); } CP_ABORT("Unknown Asset type: %s/%s", dir.c_str(), assetPath.c_str()); } CP_ABORT("Unknown Asset: %s", assetPath.c_str()); } Asset& AssetManager::LoadAsset(const UUID& uuid) { CP_DEBUG("Loading uuid Asset: %s", uuid.ToString().c_str()); for (auto&& assetFile : cachedAssetFiles) { if (assetFile.GetUUID() != uuid) continue; if (assetFile.NeedReload()) assetFile.Load(); if (assetFile.GetUUID() != uuid) continue; CP_DEBUG("Loading Asset: %s", assetFile.GetPath().c_str()); auto it = pathToAssetCache.find(assetFile.GetPath()); if (it != pathToAssetCache.end()) return *assets.find(it->second)->second.get(); MetaFile metaFile{assetFile.GetPath()}; if (metaFile.HasMetaClass("Texture2D")) { return CreateAsset(metaFile, "Texture2D"); } CP_ABORT("Unknown Asset type: %s", assetFile.GetPath().c_str()); } CP_ABORT("Asset not found with uuid=%s", uuid.ToString().c_str()); // TODO: Reload the assetCache to see if a new file has appeared with that uuid } void AssetManager::UnloadAsset(AssetHandle handle) { auto it = assets.find(handle); CP_ASSERT(it != assets.end(), "Asset not loaded"); if (it->second->isRuntime()) nameToAssetCache.erase(it->second->GetName()); else pathToAssetCache.erase(it->second->GetName()); assets.erase(it); } void AssetManager::Cleanup() { if (assets.empty()) return; CP_WARN("Cleaning up %d loaded assets", assets.size()); assets.clear(); nameToAssetCache.clear(); pathToAssetCache.clear(); } Asset& AssetManager::RegisterRuntimeAsset(const std::string& name, std::unique_ptr&& asset) { auto it = nameToAssetCache.find(name); CP_ASSERT(it == nameToAssetCache.end(), "Asset already exists: %s", name); AssetHandle handle = runtimeAssetHandle++; Asset* asset2 = assets.emplace(handle, std::move(asset)).first->second.get(); asset2->metaData.handle = handle; asset2->metaData.name = name; asset2->metaData.uuid = UUID(); asset2->metaData.isRuntime = true; nameToAssetCache.emplace(name, handle); return *asset2; } template Asset& AssetManager::CreateAsset(const MetaFile& metaFile, const std::string& metaFileClass) { AssetHandle handle = assetHandle++; pathToAssetCache.emplace(metaFile.GetFilePath(), handle); Asset& asset = *assets.emplace(handle, std::make_unique(metaFile)).first->second.get(); asset.metaData.handle = handle; asset.metaData.name = metaFile.GetFilePath(); asset.metaData.uuid = UUID{metaFile.GetMetaClass(metaFileClass).GetValue("uuid")}; asset.metaData.isRuntime = false; return asset; } }