123 lines
4.2 KiB
C++
123 lines
4.2 KiB
C++
module;
|
|
|
|
#include <cassert>
|
|
#include <map>
|
|
#include <optional>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
export module core.resource_manager;
|
|
|
|
export namespace core
|
|
{
|
|
template <typename ResourceLoaderType, typename ResourceType>
|
|
concept IsResourceLoader = requires(ResourceLoaderType loader, const std::string& name)
|
|
{
|
|
{ loader.load_resource(name) } -> std::same_as<ResourceType>;
|
|
};
|
|
|
|
template <
|
|
typename ResourceIDType,
|
|
typename ResourceType,
|
|
IsResourceLoader<ResourceType> ResourceLoaderType
|
|
>
|
|
class ResourceManager
|
|
{
|
|
// Resource loader
|
|
ResourceLoaderType& resource_loader_;
|
|
|
|
// Registry of loaded resources, array index is resource ID
|
|
std::vector<ResourceType> resource_registry_;
|
|
|
|
// Mapping of all loaded resources from (file) name to resource ID
|
|
std::map<std::string, ResourceIDType> resource_name_map_;
|
|
|
|
public:
|
|
ResourceManager() = delete;
|
|
|
|
explicit ResourceManager(ResourceLoaderType& resource_loader)
|
|
: resource_loader_{resource_loader}
|
|
{}
|
|
|
|
// No copy or move operations
|
|
ResourceManager(const ResourceManager&) = delete;
|
|
ResourceManager& operator=(const ResourceManager&) = delete;
|
|
ResourceManager(ResourceManager&&) = delete;
|
|
ResourceManager& operator=(ResourceManager&&) = delete;
|
|
|
|
~ResourceManager() = default;
|
|
|
|
/**
|
|
* Adds a new resource to the registry and returns its ID.
|
|
*/
|
|
ResourceIDType add_resource(ResourceType&& resource)
|
|
{
|
|
// Add resource to end of vector
|
|
resource_registry_.push_back(std::move(resource));
|
|
|
|
// Return the index of the newly added resource
|
|
return static_cast<ResourceIDType>(resource_registry_.size() - 1);
|
|
}
|
|
|
|
/**
|
|
* Adds a new resource to the registry, associates the name with it and returns its ID.
|
|
*/
|
|
ResourceIDType add_resource(ResourceType&& resource, const std::string& name)
|
|
{
|
|
// Add resource
|
|
ResourceIDType resource_id = add_resource(std::move(resource));
|
|
|
|
// Associate name with resource ID for future access
|
|
resource_name_map_.emplace(name, resource_id);
|
|
|
|
return resource_id;
|
|
}
|
|
|
|
/**
|
|
* Gets the resource ID for a given resource name, or `std::nullopt` if the resource was not found.
|
|
*/
|
|
std::optional<ResourceIDType> get_resource_id_by_name(const std::string& name) const
|
|
{
|
|
// Check if resource is already loaded
|
|
if (
|
|
const auto search = resource_name_map_.find(name);
|
|
search != resource_name_map_.end()
|
|
) {
|
|
// Return resource ID
|
|
return search->second;
|
|
}
|
|
|
|
return std::nullopt;
|
|
}
|
|
|
|
/**
|
|
* Loads a resource (e.g. from a file) and adds it to the registry if it isn't loaded yet.
|
|
* Returns the resource ID.
|
|
*/
|
|
ResourceIDType load_resource_by_name(const std::string& name)
|
|
{
|
|
// Check if resource is already loaded
|
|
if (
|
|
auto resource_id = get_resource_id_by_name(name);
|
|
resource_id.has_value()
|
|
) {
|
|
return resource_id.value();
|
|
}
|
|
|
|
// Load resource and add it to the registry
|
|
return add_resource(resource_loader_.load_resource(name), name);
|
|
}
|
|
|
|
/**
|
|
* Returns a reference to the resource with the given ID.
|
|
* The reference is not guaranteed to be valid after adding new resources to the registry.
|
|
* Assumes that the resource ID is valid.
|
|
*/
|
|
const ResourceType& get_resource(const ResourceIDType resource_id) const
|
|
{
|
|
assert(resource_id < resource_registry_.size());
|
|
return resource_registry_[resource_id];
|
|
}
|
|
};
|
|
}
|