#pragma once #include #include #include #include "file.hpp" #include "assetptr.hpp" #include "asset_types.hpp" #include "string_utils.hpp" namespace std { template <> struct hash { std::size_t operator()(const file::Path& k) const { return (std::hash()(k.string())); } }; } template std::unique_ptr load_asset(const file::Path p); template bool can_load_asset(const file::Path p); template using AssetStore = std::unordered_map>; template class AssetPool : public AssetStore... { public: template AssetPtr add() { const auto p = file::Path(); auto reference_block = get_reference_block(p); AssetStore::try_emplace(p, std::make_unique()); return AssetPtr(AssetStore::at(p).get(), reference_block); } template AssetPtr get(const file::Path path) { return fetch(path, get_reference_block(path)); } template std::vector get_all() { std::vector assets; for(auto iter = AssetStore::begin(); iter != AssetStore::end(); iter++) { auto& [p, asset] = *iter; assets.push_back(asset.get()); } return assets; } template AssetPtr fetch(const file::Path path, ReferenceBlock* reference_block) { if(!AssetStore::count(path)) AssetStore::try_emplace(path, load_asset(path)); return AssetPtr(AssetStore::at(path).get(), reference_block); } std::tuple load_asset_generic(const file::Path path) { Asset* asset = nullptr; ReferenceBlock* block = nullptr; (load_asset_generic(path, asset, block), ...); return {asset, block}; } void perform_cleanup() { for(auto iter = reference_blocks.begin(); iter != reference_blocks.end();) { auto& [path, block] = *iter; if(block->references == 0) { ((delete_asset(path)), ...); iter = reference_blocks.erase(iter); } else { iter = std::next(iter); } } } std::unordered_map> reference_blocks; private: ReferenceBlock* get_reference_block(const file::Path path) { if(!reference_blocks.count(path)) reference_blocks.try_emplace(path, std::make_unique()); return reference_blocks[path].get(); } template void load_asset_generic(const file::Path path, Asset*& at, ReferenceBlock*& block) { if(can_load_asset(path)) { if(!AssetStore::count(path)) AssetStore::try_emplace(path, load_asset(path)); at = AssetStore::at(path).get(); block = get_reference_block(path); } } template void delete_asset(const file::Path path) { auto iter = AssetStore::find(path); if(iter != AssetStore::end()) { auto& [_, asset] = *iter; asset.reset(); AssetStore::erase(iter); } } }; using AssetManager = AssetPool; inline std::unique_ptr assetm; std::unique_ptr load_mesh(const file::Path path); std::unique_ptr load_material(const file::Path path); std::unique_ptr load_texture(const file::Path path); void save_material(Material* material, const file::Path path); template std::unique_ptr load_asset(const file::Path path) { if constexpr (std::is_same_v) { return load_mesh(path); } else if constexpr(std::is_same_v) { return load_material(path); } else if constexpr(std::is_same_v) { return load_texture(path); } } template bool can_load_asset(const file::Path path) { if constexpr(std::is_same_v) { return path.extension() == ".model"; } else if constexpr(std::is_same_v) { return path.extension() == ".material"; } else if constexpr(std::is_same_v) { return path.extension() == ".png"; } }