Chira Engine
A customizable MIT-licensed game engine.
Resource.cpp
1 #include "Resource.h"
2 
3 #include <core/Logger.h>
4 #include <i18n/TranslationManager.h>
5 
6 using namespace chira;
7 
8 CHIRA_CREATE_LOG(RESOURCE);
9 
10 Resource::~Resource() {
11  Resource::removeResource(this->identifier);
12 }
13 
14 //
15 // Static caching functions
16 //
17 
18 void Resource::addResourceProvider(IResourceProvider* provider) {
19  std::string providerName{provider->getName().data()};
20  if (Resource::providers.find(providerName) == Resource::providers.end()) {
21  Resource::providers[providerName] = std::vector<std::unique_ptr<IResourceProvider>>{};
22  }
23  Resource::providers[providerName].emplace_back(provider);
24 }
25 
26 IResourceProvider* Resource::getLatestResourceProvider(const std::string& provider) {
27  return Resource::providers[provider][Resource::providers[provider].size() - 1].get();
28 }
29 
30 IResourceProvider* Resource::getResourceProviderWithResource(const std::string& identifier) {
31  auto id = Resource::splitResourceIdentifier(identifier);
32  const std::string& provider = id.first, name = id.second;
33  for (auto i = Resource::providers[provider].rbegin(); i < Resource::providers[provider].rend(); i++) {
34  if (i->get()->hasResource(name))
35  return i->get();
36  }
37  LOG_RESOURCE.error(TRF("error.resource.resource_not_found", identifier));
38  return nullptr;
39 }
40 
41 std::pair<std::string, std::string> Resource::splitResourceIdentifier(const std::string& identifier) {
42  std::pair<std::string, std::string> out;
43  size_t pos = identifier.find(RESOURCE_ID_SEPARATOR);
44  if (pos != std::string::npos) {
45  out.first = identifier.substr(0, pos);
46  out.second = identifier.substr(pos + RESOURCE_ID_SEPARATOR.length());
47  } else {
48  LOG_RESOURCE.error(TRF("error.resource.cannot_split_identifier", identifier));
49  }
50  return out;
51 }
52 
53 const std::vector<std::unique_ptr<IResourceProvider>>& Resource::getResourceProviders(const std::string& providerName) {
54  return Resource::providers.at(providerName);
55 }
56 
57 bool Resource::hasResource(const std::string& identifier) {
58  auto id = Resource::splitResourceIdentifier(identifier);
59  const std::string& provider = id.first, name = id.second;
60  for (auto i = Resource::providers[provider].rbegin(); i != Resource::providers[provider].rend(); i++) {
61  if (i->get()->hasResource(name))
62  return true;
63  }
64  return false;
65 }
66 
67 void Resource::removeResource(const std::string& identifier) {
68  auto id = Resource::splitResourceIdentifier(identifier);
69  const std::string& provider = id.first, name = id.second;
70  // If the count is 2, then it's being held by the resource manager and the object requesting its removal.
71  // Anything below 2 means it should be already deleted everywhere except the resource manager.
72  if (Resource::resources[provider].contains(name) && Resource::resources[provider][name].useCount() <= 2)
73  Resource::garbageResources.push_back(identifier);
74 }
75 
77  for (const auto& name : Resource::garbageResources) {
78  auto id = Resource::splitResourceIdentifier(name);
79  Resource::resources[id.first].erase(id.second);
80  }
81  Resource::garbageResources.clear();
82 }
83 
85  Resource::defaultResources.clear();
87  for (const auto& [providerName, resourceMap] : Resource::resources) {
88  for (const auto& [name, resource] : resourceMap) {
89  // This really shouldn't happen, but it should work out if it does, hence the warning
90  LOG_RESOURCE.warning() << TRF("warn.resource.deleting_resource_at_exit",
91  Resource::resources[providerName].at(name)->getIdentifier(),
92  Resource::resources[providerName].at(name).useCount());
93  }
94  }
95  Resource::resources.clear();
96  Resource::providers.clear();
97 }
98 
99 void Resource::logResourceError(const std::string& identifier, const std::string& resourceName) {
100  LOG_RESOURCE.error(TRF(identifier, resourceName));
101 }
static void logResourceError(const std::string &identifier, const std::string &resourceName)
We do a few predeclaration workarounds.
Definition: Resource.cpp:99
static void removeResource(const std::string &identifier)
If resource is present in the cache and has a reference count less than or equal to 2,...
Definition: Resource.cpp:67
static void cleanup()
Delete all resources marked for removal.
Definition: Resource.cpp:76
static void discardAll()
Deletes ALL resources and providers. Should only ever be called once, when the program closes.
Definition: Resource.cpp:84