00001 /* Crown and Cutlass 00002 * Resource Manager Code 00003 */ 00004 00005 #include <string> 00006 #include <map> 00007 #include <vector> 00008 #include "../Log.h" 00009 #include "../tinyxml.h" 00010 #include "../ccmath.h" 00011 #include "IResource.h" 00012 #include "IResourceFactory.h" 00013 #include "ResourceManager.h" 00014 00015 using namespace std; 00016 00017 struct ResourceEntry { 00018 IResource *resource; 00019 unsigned int refCount; 00020 }; 00021 00022 ResourceManager* ResourceManager::s_resourceManager = NULL; 00023 00024 ResourceManager::ResourceManager() { 00025 // Does anything need to happen here? 00026 Log::s_log->Message("Resource manager initialized"); 00027 } 00028 00029 ResourceManager::~ResourceManager() { 00030 ResourceEntry *entry; 00031 string key; 00032 00033 m_typeVectors.clear(); 00034 00035 // Loop through all the resources, free them and the ResourceEntry the map was using 00036 while (!m_resources.empty()) { 00037 entry = m_resources.begin()->second; 00038 key = m_resources.begin()->first; 00039 delete entry->resource; 00040 m_resources.erase(key); 00041 delete entry; 00042 } 00043 00044 if (!m_resources.empty()) { 00045 Log::s_log->Message("Warning: Could not empty resource map"); 00046 } 00047 00048 Log::s_log->Message("Resource manager shut down"); 00049 } 00050 00051 IResource* ResourceManager::Acquire(string key) { 00052 ResourceEntry *entry; 00053 00054 entry = m_resources[key]; 00055 if (entry == NULL) { 00056 throw string("Key not found in resource map (" + key + ")"); 00057 } 00058 00059 return DoAcquireResource(entry); 00060 } 00061 00062 IResource* ResourceManager::AcquireRandom(string type) { 00063 ResourceEntryVector resources; 00064 unsigned int index; 00065 ResourceEntry *entry; 00066 00067 resources = m_typeVectors[type]; 00068 if (resources.empty()) { 00069 throw string("Zero resources of type " + type + " found"); 00070 } 00071 00072 index = (unsigned int) randInt(resources.size() - 1); 00073 entry = resources[index]; 00074 Log::s_log->Message("Got random resource: %s", entry->resource->GetKey().c_str()); 00075 00076 return DoAcquireResource(entry); 00077 } 00078 00079 IResource* ResourceManager::DoAcquireResource(ResourceEntry *entry) { 00080 // Check to see if this is the first use of this resource, load it if it is 00081 if (entry->refCount == 0) { 00082 entry->resource->Load(); 00083 } 00084 // Increment the reference count 00085 ++entry->refCount; 00086 00087 return entry->resource; 00088 } 00089 00090 void ResourceManager::Release(IResource *resource) { 00091 ResourceEntry *entry; 00092 00093 entry = m_resources[resource->GetKey()]; 00094 if (entry == NULL) { 00095 throw string("Key not found in resource map (" + resource->GetKey() + ")"); 00096 } 00097 00098 // Decrement the reference count 00099 --entry->refCount; 00100 // Check to see if we are releasing the last reference to this resource, and unload it if we are 00101 if (entry->refCount == 0) { 00102 entry->resource->Unload(); 00103 } 00104 } 00105 00106 void ResourceManager::LoadXMLFile(std::string filename, auto_ptr<IResourceFactory> factory) { 00107 TiXmlElement *elem; 00108 TiXmlDocument doc( filename.c_str() ); 00109 00110 doc.LoadFile(); 00111 if (doc.Error()) { 00112 // Should throw an exception 00113 Log::s_log->Message("Warning: Could not load %s. %s (line %d, column %d)", filename.c_str(), doc.ErrorDesc(), doc.ErrorRow(), doc.ErrorCol()); 00114 return; 00115 } 00116 00117 for (elem = doc.FirstChildElement("Resources")->FirstChildElement("Resource"); elem; elem = elem->NextSiblingElement("Resource")) { 00118 ResourceEntry *entry = new ResourceEntry; 00119 entry->refCount = 0; 00120 try { 00121 entry->resource = factory->NewResource(elem); 00122 if (entry->resource == NULL) { 00123 throw string("Factory returned null pointer"); 00124 } 00125 m_resources[entry->resource->GetKey()] = entry; 00126 00127 m_typeVectors[entry->resource->GetType()].push_back(entry); 00128 } catch (string e) { 00129 delete entry; 00130 throw e; 00131 } 00132 } 00133 00134 Log::s_log->Message("Resource file %s loaded", filename.c_str()); 00135 } 00136 00137 void ResourceManager::LogDebugInfo() { 00138 Log::s_log->Message("%d total resources", m_resources.size()); 00139 } 00140 00141 void ResourceManager::Initialize() { 00142 if (s_resourceManager != NULL) { 00143 Log::s_log->Message("Warning: Attempt to re-initialize resource manager"); 00144 return; 00145 } 00146 00147 s_resourceManager = new ResourceManager(); 00148 } 00149 00150 void ResourceManager::Shutdown() { 00151 if (s_resourceManager == NULL) { 00152 Log::s_log->Message("Warning: Attempt to re-shutdown resource manager"); 00153 return; 00154 } 00155 delete s_resourceManager; 00156 s_resourceManager = NULL; 00157 } 00158
1.4.7