engine/include/resource_manager.hpp

85 lines
2.2 KiB
C++
Raw Normal View History

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