00001 /* 00002 ----------------------------------------------------------------------------- 00003 This source file is part of OGRE 00004 (Object-oriented Graphics Rendering Engine) 00005 For the latest info, see http://www.ogre3d.org/ 00006 00007 Copyright © 2000-2002 The OGRE Team 00008 Also see acknowledgements in Readme.html 00009 00010 This program is free software; you can redistribute it and/or modify it under 00011 the terms of the GNU Lesser General Public License as published by the Free Software 00012 Foundation; either version 2 of the License, or (at your option) any later 00013 version. 00014 00015 This program is distributed in the hope that it will be useful, but WITHOUT 00016 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 00017 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. 00018 00019 You should have received a copy of the GNU Lesser General Public License along with 00020 this program; if not, write to the Free Software Foundation, Inc., 59 Temple 00021 Place - Suite 330, Boston, MA 02111-1307, USA, or go to 00022 http://www.gnu.org/copyleft/lesser.txt. 00023 ----------------------------------------------------------------------------- 00024 */ 00025 #include "OgreStableHeaders.h" 00026 #include "OgreResourceManager.h" 00027 00028 #include "OgreException.h" 00029 #include "OgreArchiveEx.h" 00030 #include "OgreArchiveManager.h" 00031 #include "OgreStringVector.h" 00032 #include "OgreStringConverter.h" 00033 00034 namespace Ogre { 00035 00036 std::vector<ArchiveEx*> ResourceManager::mCommonVFS; 00037 ResourceManager::FileMap ResourceManager::mCommonArchiveFiles; 00038 00041 static String convertPath( const String &init) 00042 { 00043 String path = init; 00044 00045 std::replace( path.begin(), path.end(), '\\', '/' ); 00046 if( path[path.length() - 1] != '/' ) 00047 path += '/'; 00048 00049 return path; 00050 } 00051 00052 //----------------------------------------------------------------------- 00053 ResourceManager::ResourceManager() 00054 { 00055 // Init memory limit & usage 00056 mMemoryBudget = std::numeric_limits<unsigned long>::max(); 00057 mMemoryUsage = 0; 00058 mNextHandle = 1; 00059 } 00060 //----------------------------------------------------------------------- 00061 ResourceManager::~ResourceManager() 00062 { 00063 this->unloadAndDestroyAll(); 00064 } 00065 00066 //----------------------------------------------------------------------- 00067 void ResourceManager::load(Resource *res, int priority) 00068 { 00069 res->load(); 00070 res->touch(); 00071 this->add(res); 00072 } 00073 00074 //----------------------------------------------------------------------- 00075 void ResourceManager::add( Resource *res ) 00076 { 00077 std::pair<ResourceMap::iterator, bool> result = 00078 mResources.insert( ResourceMap::value_type( res->getName(), res ) ); 00079 if (!result.second) 00080 { 00081 Except(Exception::ERR_DUPLICATE_ITEM, "Resource with the name " + res->getName() + 00082 " already exists.", "ResourceManager::add"); 00083 } 00084 // Assign a new handle 00085 res->mHandle = getNextHandle(); 00086 std::pair<ResourceHandleMap::iterator, bool> resultHandle = 00087 mResourcesByHandle.insert( ResourceHandleMap::value_type( res->mHandle, res ) ); 00088 if (!result.second) 00089 { 00090 Except(Exception::ERR_DUPLICATE_ITEM, "Resource with the handle " + 00091 StringConverter::toString(res->mHandle) + 00092 " already exists.", "ResourceManager::add"); 00093 } 00094 00095 } 00096 //----------------------------------------------------------------------- 00097 void ResourceManager::setMemoryBudget( size_t bytes) 00098 { 00099 // Update limit & check usage 00100 mMemoryBudget = bytes; 00101 checkUsage(); 00102 } 00103 00104 //----------------------------------------------------------------------- 00105 void ResourceManager::unload(Resource* res) 00106 { 00107 if (!res) 00108 return; 00109 00110 // Unload resource 00111 res->unload(); 00112 00113 // Erase entry in map 00114 mResources.erase( res->getName() ); 00115 mResourcesByHandle.erase( res->getHandle() ); 00116 00117 // Update memory usage 00118 mMemoryUsage -= res->getSize(); 00119 } 00120 00121 //----------------------------------------------------------------------- 00122 void ResourceManager::unloadAndDestroyAll() 00123 { 00124 // Unload & delete resources in turn 00125 for( 00126 ResourceMap::iterator it = mResources.begin(); 00127 it != mResources.end(); 00128 ++it) 00129 { 00130 it->second->unload(); 00131 it->second->destroy(); 00132 } 00133 00134 // Empty the list 00135 mResources.clear(); 00136 mResourcesByHandle.clear(); 00137 } 00138 //----------------------------------------------------------------------- 00139 Resource* ResourceManager::getByName(const String& name) 00140 { 00141 ResourceMap::iterator it = mResources.find(name); 00142 00143 if( it == mResources.end() ) 00144 return 0; 00145 else 00146 { 00147 return it->second; 00148 } 00149 } 00150 //----------------------------------------------------------------------- 00151 Resource* ResourceManager::getByHandle(ResourceHandle handle) 00152 { 00153 ResourceHandleMap::iterator it = mResourcesByHandle.find(handle); 00154 if (it == mResourcesByHandle.end()) 00155 { 00156 return NULL; 00157 } 00158 else 00159 { 00160 it->second->touch(); 00161 return it->second; 00162 } 00163 } 00164 //----------------------------------------------------------------------- 00165 ResourceHandle ResourceManager::getNextHandle(void) 00166 { 00167 return mNextHandle++; 00168 } 00169 //----------------------------------------------------------------------- 00170 void ResourceManager::checkUsage(void) 00171 { 00172 // Page out here? 00173 } 00174 00175 //----------------------------------------------------------------------- 00176 void ResourceManager::addSearchPath( const String& path) 00177 { 00178 addArchiveEx( convertPath(path), "FileSystem" ); 00179 } 00180 00181 //----------------------------------------------------------------------- 00182 void ResourceManager::addCommonSearchPath( const String& path) 00183 { 00184 addCommonArchiveEx( convertPath(path), "FileSystem" ); 00185 } 00186 00187 //----------------------------------------------------------------------- 00188 void ResourceManager::addArchiveEx( const String& strName, const String& strDriverName ) 00189 { 00190 ArchiveEx* pArch = ArchiveManager::getSingleton().load( strName, strDriverName ); 00191 00192 StringVector vec = pArch->getAllNamesLike( "", "" ); 00193 for( StringVector::iterator it = vec.begin(); it != vec.end(); ++it ) 00194 mArchiveFiles[(*it)] = pArch; 00195 00196 mVFS.push_back(pArch); 00197 } 00198 00199 //----------------------------------------------------------------------- 00200 void ResourceManager::addCommonArchiveEx( const String& strName, const String& strDriverName ) 00201 { 00202 ArchiveEx* pArch = ArchiveManager::getSingleton().load( strName, strDriverName ); 00203 00204 StringVector vec = pArch->getAllNamesLike( "", "" ); 00205 for( StringVector::iterator it = vec.begin(); it != vec.end(); ++it ) 00206 mCommonArchiveFiles[(*it)] = pArch; 00207 00208 mCommonVFS.push_back(pArch); 00209 } 00210 00211 //----------------------------------------------------------------------- 00212 bool ResourceManager::_findResourceData( 00213 const String& filename, 00214 DataChunk& refChunk ) 00215 { 00216 DataChunk* pChunk = &refChunk; 00217 // Search file cache first 00218 // NB don't treat this as definitive, incase ArchiveEx can't list all existing files 00219 FileMap::const_iterator it; 00220 if( ( it = mArchiveFiles.find( filename ) ) != mArchiveFiles.end() ) 00221 return it->second->fileRead( filename, &pChunk ); 00222 if( ( it = mCommonArchiveFiles.find( filename ) ) != mCommonArchiveFiles.end() ) 00223 return it->second->fileRead( filename, &pChunk ); 00224 00225 // Not found in cache 00226 // Look for it the hard way 00227 std::vector<ArchiveEx*>::iterator j; 00228 // Search archives specific to this resource type 00229 for(j = mVFS.begin(); j != mVFS.end(); ++j ) 00230 { 00231 if( *j && (*j)->fileTest(filename) ) 00232 { 00233 return (*j)->fileRead( filename, &pChunk ); 00234 } 00235 } 00236 // Search common archives 00237 for(j = mCommonVFS.begin(); j != mCommonVFS.end(); ++j ) 00238 { 00239 if( *j && (*j)->fileTest(filename) ) 00240 { 00241 return (*j)->fileRead( filename, &pChunk ); 00242 } 00243 } 00244 00245 // Not found 00246 Except( 00247 Exception::ERR_ITEM_NOT_FOUND, 00248 "Resource " + filename + " not found.", 00249 "ResourceManager::_findResourceData" ); 00250 00251 // To keep compiler happy 00252 return false; 00253 } 00254 //----------------------------------------------------------------------- 00255 std::set<String> ResourceManager::_getAllCommonNamesLike( const String& startPath, const String& extension ) 00256 { 00257 std::vector<ArchiveEx*>::iterator i; 00258 StringVector vecFiles; 00259 std::set<String> retFiles; 00260 00261 // search common archives 00262 for (i = mCommonVFS.begin(); i != mCommonVFS.end(); ++i) 00263 { 00264 vecFiles = (*i)->getAllNamesLike( startPath, extension); 00265 for (StringVector::iterator si = vecFiles.begin(); si != vecFiles.end(); ++si) 00266 { 00267 retFiles.insert(*si); 00268 } 00269 } 00270 00271 return retFiles; 00272 } 00273 //----------------------------------------------------------------------- 00274 std::set<String> ResourceManager::_getAllNamesLike( const String& startPath, const String& extension ) 00275 { 00276 std::vector<ArchiveEx*>::iterator i; 00277 StringVector vecFiles; 00278 // Get all common files 00279 std::set<String> retFiles = ResourceManager::_getAllCommonNamesLike(startPath, extension); 00280 00281 // Get all specific files 00282 for (i = mVFS.begin(); i != mVFS.end(); ++i) 00283 { 00284 vecFiles = (*i)->getAllNamesLike( startPath, extension); 00285 for (StringVector::iterator si = vecFiles.begin(); si != vecFiles.end(); ++si) 00286 { 00287 retFiles.insert(*si); 00288 } 00289 } 00290 00291 return retFiles; 00292 } 00293 //----------------------------------------------------------------------- 00294 bool ResourceManager::_findCommonResourceData( const String& filename, DataChunk& refChunk ) 00295 { 00296 DataChunk* pChunk = &refChunk; 00297 // Search file cache first 00298 // NB don't treat this as definitive, incase ArchiveEx can't list all existing files 00299 FileMap::const_iterator it; 00300 if( ( it = mCommonArchiveFiles.find( filename ) ) != mCommonArchiveFiles.end() ) 00301 return it->second->fileRead( filename, &pChunk ); 00302 00303 // Not found in cache 00304 // Look for it the hard way 00305 std::vector<ArchiveEx*>::iterator j; 00306 // Search common archives 00307 for(j = mCommonVFS.begin(); j != mCommonVFS.end(); ++j ) 00308 { 00309 if( *j && (*j)->fileTest(filename) ) 00310 { 00311 return (*j)->fileRead( filename, &pChunk ); 00312 } 00313 } 00314 00315 // Not found 00316 Except( 00317 Exception::ERR_ITEM_NOT_FOUND, 00318 "Resource " + filename + " not found.", 00319 "ResourceManager::_findCommonResourceData" ); 00320 00321 // To keep compiler happy 00322 return false; 00323 } 00324 00325 } 00326 00327 00328
Copyright © 2002-2003 by The OGRE Team
Last modified Wed Jan 21 00:10:25 2004