LumixEngine/src/engine/resource_manager.cpp
Mikulas Florek 9b399880ad cleanup
2019-06-21 17:14:06 +02:00

250 lines
5 KiB
C++

#include "engine/log.h"
#include "engine/lumix.h"
#include "engine/resource.h"
#include "engine/resource_manager.h"
namespace Lumix
{
void ResourceManager::create(ResourceType type, ResourceManagerHub& owner)
{
owner.add(type, this);
m_owner = &owner;
}
void ResourceManager::destroy()
{
for (auto iter = m_resources.begin(), end = m_resources.end(); iter != end; ++iter)
{
Resource* resource = iter.value();
if (!resource->isEmpty())
{
logError("Engine") << "Leaking resource " << resource->getPath().c_str() << "\n";
}
destroyResource(*resource);
}
m_resources.clear();
}
Resource* ResourceManager::get(const Path& path)
{
ResourceTable::iterator it = m_resources.find(path.getHash());
if(m_resources.end() != it)
{
return *it;
}
return nullptr;
}
Resource* ResourceManager::load(const Path& path)
{
if (!path.isValid()) return nullptr;
Resource* resource = get(path);
if(nullptr == resource)
{
resource = createResource(path);
m_resources.insert(path.getHash(), resource);
}
if(resource->isEmpty() && resource->m_desired_state == Resource::State::EMPTY)
{
if (m_owner->onBeforeLoad(*resource) == ResourceManagerHub::LoadHook::Action::DEFERRED)
{
resource->m_desired_state = Resource::State::READY;
resource->addRef(); // for hook
resource->addRef(); // for return value
return resource;
}
resource->doLoad();
}
resource->addRef();
return resource;
}
void ResourceManager::removeUnreferenced()
{
if (!m_is_unload_enabled) return;
Array<Resource*> to_remove(m_allocator);
for (auto* i : m_resources)
{
if (i->getRefCount() == 0) to_remove.push(i);
}
for (auto* i : to_remove)
{
m_resources.erase(i->getPath().getHash());
destroyResource(*i);
}
}
void ResourceManager::load(Resource& resource)
{
if(resource.isEmpty() && resource.m_desired_state == Resource::State::EMPTY)
{
if (m_owner->onBeforeLoad(resource) == ResourceManagerHub::LoadHook::Action::DEFERRED)
{
resource.addRef(); // for hook
return;
}
resource.doLoad();
}
resource.addRef();
}
void ResourceManager::unload(const Path& path)
{
Resource* resource = get(path);
if (resource) unload(*resource);
}
void ResourceManager::unload(Resource& resource)
{
int new_ref_count = resource.remRef();
ASSERT(new_ref_count >= 0);
if(new_ref_count == 0 && m_is_unload_enabled)
{
resource.doUnload();
}
}
void ResourceManager::reload(const Path& path)
{
Resource* resource = get(path);
if(resource) reload(*resource);
}
void ResourceManager::reload(Resource& resource)
{
resource.doUnload();
if (m_owner->onBeforeLoad(resource) == ResourceManagerHub::LoadHook::Action::DEFERRED)
{
resource.m_desired_state = Resource::State::READY;
resource.addRef(); // for hook
resource.addRef(); // for return value
}
else {
resource.doLoad();
}
}
void ResourceManager::enableUnload(bool enable)
{
m_is_unload_enabled = enable;
if (!enable) return;
for (auto* resource : m_resources)
{
if (resource->getRefCount() == 0)
{
resource->doUnload();
}
}
}
ResourceManager::ResourceManager(IAllocator& allocator)
: m_resources(allocator)
, m_allocator(allocator)
, m_owner(nullptr)
, m_is_unload_enabled(true)
{ }
ResourceManager::~ResourceManager()
{
ASSERT(m_resources.empty());
}
ResourceManagerHub::ResourceManagerHub(IAllocator& allocator)
: m_resource_managers(allocator)
, m_allocator(allocator)
, m_load_hook(nullptr)
, m_file_system(nullptr)
{
}
ResourceManagerHub::~ResourceManagerHub() = default;
void ResourceManagerHub::init(FileSystem& fs)
{
m_file_system = &fs;
}
Resource* ResourceManagerHub::load(ResourceType type, const Path& path)
{
ResourceManager* manager = get(type);
if(!manager) return nullptr;
return load(*manager, path);
}
Resource* ResourceManagerHub::load(ResourceManager& manager, const Path& path)
{
return manager.load(path);
}
ResourceManager* ResourceManagerHub::get(ResourceType type)
{
return m_resource_managers[type.type];
}
void ResourceManagerHub::LoadHook::continueLoad(Resource& resource)
{
ASSERT(resource.isEmpty());
resource.remRef(); // release from hook
resource.m_desired_state = Resource::State::EMPTY;
resource.doLoad();
}
void ResourceManagerHub::setLoadHook(LoadHook* hook)
{
ASSERT(!m_load_hook || !hook);
m_load_hook = hook;
}
ResourceManagerHub::LoadHook::Action ResourceManagerHub::onBeforeLoad(Resource& resource) const
{
return m_load_hook ? m_load_hook->onBeforeLoad(resource) : LoadHook::Action::IMMEDIATE;
}
void ResourceManagerHub::add(ResourceType type, ResourceManager* rm)
{
m_resource_managers.insert(type.type, rm);
}
void ResourceManagerHub::remove(ResourceType type)
{
m_resource_managers.erase(type.type);
}
void ResourceManagerHub::removeUnreferenced()
{
for (auto* manager : m_resource_managers)
{
manager->removeUnreferenced();
}
}
void ResourceManagerHub::enableUnload(bool enable)
{
for (auto* manager : m_resource_managers)
{
manager->enableUnload(enable);
}
}
void ResourceManagerHub::reload(const Path& path)
{
for (auto* manager : m_resource_managers)
{
manager->reload(path);
}
}
} // namespace Lumix