#pragma once #include "resources/resource.hpp" #include #include // Doesn't own resources, only holds weak_ptrs class ResourceManager { public: ResourceManager(); ResourceManager(const ResourceManager&) = delete; ResourceManager& operator=(const ResourceManager&) = delete; ~ResourceManager() = default; template std::shared_ptr create(const std::string& name); // creates the resource if it is not in the map or the weak_ptr has expired template std::shared_ptr get(const std::string& name); std::unique_ptr getResourcesListString(); std::vector> getAllResourcesOfType(const std::string& type); std::filesystem::path getFilePath(const std::string& name); private: std::filesystem::path m_resourcesPath; std::unordered_map> m_resources; }; template std::shared_ptr ResourceManager::create(const std::string& name) { if (std::is_base_of::value == false) { throw std::runtime_error("ResourceManager::create() error: specified type is not a subclass of 'Resource'"); } auto resource = std::make_shared(getFilePath(name)); m_resources.emplace(name, std::dynamic_pointer_cast(resource)); return resource; } template std::shared_ptr ResourceManager::get(const std::string& name) { if (std::is_base_of::value == false) { throw std::runtime_error("ResourceManager::get() error: specified type is not a subclass of 'Resource'"); } if (m_resources.contains(name)) { std::weak_ptr res = m_resources.at(name); if (res.expired() == false) { // resource definitely exists auto castedSharedPtr = std::dynamic_pointer_cast(res.lock()); if (castedSharedPtr == nullptr) { throw std::runtime_error("error: attempt to get Resource which already exists as another type"); } else { return castedSharedPtr; } } else { // Resource in map but no longer exists. Delete it. m_resources.erase(name); } } return create(name); }