ResourceLoader.cpp

00001 /***************************************************************************
00002  *                                                                         *
00003  *   (c) Art Tevs, MPI Informatik Saarbruecken                             *
00004  *       mailto: <tevs@mpi-sb.mpg.de>                                      *
00005  *                                                                         *
00006  *   This program is free software; you can redistribute it and/or modify  *
00007  *   it under the terms of the GNU General Public License as published by  *
00008  *   the Free Software Foundation; either version 2 of the License, or     *
00009  *   (at your option) any later version.                                   *
00010  *                                                                         *
00011  ***************************************************************************/
00012 
00013 
00014 //----------------------------------------------------------------------------------
00015 // Includes
00016 //----------------------------------------------------------------------------------
00017 #include "ResourceLoader.h"
00018 #include "Log.h"
00019 #include "Exception.h"
00020 #include "Engine.h"
00021 #include "ResourceManager.h"
00022 
00023 namespace nrEngine{
00024 
00025         //----------------------------------------------------------------------------------
00026         IResourceLoader::IResourceLoader(const std::string& name) : mName(name)
00027         {
00028 
00029         }
00030 
00031         //----------------------------------------------------------------------------------
00032         IResourceLoader::~IResourceLoader()
00033         {
00034                 // copy the list in another list, so we can iterate and remove them
00035                 std::vector<SharedPtr<IResource> > lst;
00036                 for (ResourceList::iterator it = mHandledResources.begin(); it != mHandledResources.end(); it ++)
00037                         lst.push_back(*it);
00038 
00039                 // now go through the vector and remove elements
00040                 for (uint32 i=0; i < lst.size(); i++)
00041                         remove(lst[i]);
00042         }
00043 
00044         //----------------------------------------------------------------------------------
00045         SharedPtr<IResource> IResourceLoader::load(const std::string& name, const std::string& group, const std::string& fileName, const std::string& resourceType, PropertyList* param)
00046         {
00047                 // check if a such resource already registered by the manager
00048                 if (Engine::sResourceManager()->isResourceRegistered(name))
00049                 {
00050                         NR_Log(Log::LOG_ENGINE, Log::LL_ERROR, "ResourceLoader: You are trying to load resource %s which is already loaded.", name.c_str());
00051                         return SharedPtr<IResource>();
00052                 }
00053 
00054                 bool typeFound = false;
00055                 std::string type;
00056                 std::string newFileName = fileName;
00057                 
00058                 // we search for the type if no type is specified
00059                 if (resourceType.length() == 0)
00060                 {
00061                         NR_Log(Log::LOG_ENGINE, Log::LL_DEBUG, "ResourceLoader \"%s\" try to find according resource type by filename \"%s\"", mName.c_str(), fileName.c_str(), fileName.c_str());
00062 
00063                         // detect the file type by reading out it's last characters
00064                         for (int32 i = fileName.length()-1; i >= 0 && !typeFound; i--){
00065                                 if ((char)fileName[i] == '.'){
00066                                         typeFound = true;
00067                                 }
00068                                 if (!typeFound) type = (char)fileName[i] + type;
00069                         }
00070                         if (!typeFound) type = "";
00071 
00072                         // check whenever the given file name is supported by the resource
00073                         if (typeFound && !supportFileType(type))
00074                         {
00075                                 NR_Log(Log::LOG_ENGINE, Log::LL_ERROR, "ResourceLoader \"%s\" can not load file of type \".%s\", because the type is not supported", mName.c_str(), type.c_str());
00076                                 return SharedPtr<IResource>();
00077                         }
00078 
00079                         #if 0
00080                         // if no type foud, then check if suffix is defined
00081                         if (!typeFound && resourceType.length() > 0)
00082                         {
00083                                 type = getSuffix(resourceType);
00084                                 if (type.length() > 0)
00085                                 {       
00086                                         typeFound = true;
00087                                         newFileName = fileName + std::string(".") + type;
00088                                 }
00089                         }
00090                         #endif
00091                                                 
00092                         // if no type was specified so give up
00093                         if (!typeFound)
00094                         {
00095                                 NR_Log(Log::LOG_ENGINE, Log::LL_ERROR, "ResourceLoader %s: neither resource type nor valid file ending was found, give up!", mName.c_str());
00096                                 return SharedPtr<IResource>();
00097                         }
00098                 }
00099 
00100                 // ok the name is supported, so now create a instance
00101                 SharedPtr<IResource> res;
00102                 if (resourceType.length() == 0){
00103                         res = create(mapFileTypeToResourceType(type), param);
00104                 }else{
00105                         res = create(resourceType, param);
00106                 }
00107                 if (res.get() == NULL) return res;
00108 
00109                 // setup some data on resource
00110                 res->addResourceFilename(newFileName);
00111                 res->mResName = name;
00112                 res->mResGroup = group;
00113 
00114                 // now call the implemented loading function
00115                 if (loadResource(res.get(), newFileName, param) != OK)
00116                 {
00117                         NR_Log(Log::LOG_ENGINE, Log::LL_ERROR, "ResourceLoader %s can not load resource from file %s", mName.c_str(), newFileName.c_str());
00118                         remove(res);
00119                         return SharedPtr<IResource>();
00120                 }
00121                 res->mResIsLoaded = true;
00122 
00123                 // now notify the resource manager, that a new resource was loaded
00124                 Engine::sResourceManager()->notifyLoaded(res.get());
00125 
00126                 return res;
00127         }
00128 
00129         //----------------------------------------------------------------------------------
00130         SharedPtr<IResource> IResourceLoader::create(const std::string& resourceType, PropertyList* params)
00131         {
00132                 NR_Log(Log::LOG_ENGINE, Log::LL_DEBUG, "ResourceLoader: Create resource of type %s", resourceType.c_str());
00133 
00134                 // first check if this type of resource is supported
00135                 if (!supportResourceType(resourceType))
00136                 {
00137                         NR_Log(Log::LOG_ENGINE, Log::LL_ERROR, "ResourceLoader %s does not support resources of type %s", mName.c_str(), resourceType.c_str());
00138                         return SharedPtr<IResource>();
00139                 }
00140 
00141                 // now call the implemented function to create the resource
00142                 SharedPtr<IResource> res (createResource(resourceType, params), IResource::_deleter());
00143 
00144                 // check if the result is valid, then add it into our database
00145                 if (res.get() == NULL) return SharedPtr<IResource>();
00146 
00147                 // now check if we have to create an empty resource for this type
00148                 SharedPtr<IResource> empty = Engine::sResourceManager()->getEmpty(resourceType);
00149 
00150                 // if not created before, so create it and register by the manager
00151                 if (empty == NULL)
00152                 {
00153                         // create empty resource and fill default properties
00154                         empty.reset( createEmptyResource(resourceType), IResource::_deleter() );
00155                         empty->mResGroup = "_Empty_Resource_Group_";
00156                         empty->mResName = "_Empty_" + resourceType;
00157                         empty->mResHandle = Engine::sResourceManager()->getNewHandle();
00158                         empty->mResIsEmpty = true;
00159                         empty->mResLoader = getSharedPtrFromThis();
00160                         empty->setResourceType(resourceType);
00161                         
00162                         // set the resource in the manager
00163                         Engine::sResourceManager()->setEmpty(resourceType, empty);
00164                 }
00165 
00166                 // setup default resource data
00167                 res->setResourceType(resourceType);
00168                 res->mResHandle = Engine::sResourceManager()->getNewHandle();
00169                 res->mResIsEmpty = false;
00170                 res->mResLoader = getSharedPtrFromThis();
00171                 
00172                 // now set this resource in the list of handled resource objects
00173                 mHandledResources.push_back(res);
00174 
00175                 // ok now return the instance
00176                 return res;
00177         }
00178 
00179         //----------------------------------------------------------------------------------
00180         SharedPtr<IResource> IResourceLoader::create(const std::string& name, const std::string& group, const std::string& resourceType, PropertyList* params)
00181         {
00182                 // first check if this type of resource is supported
00183                 if (!supportResourceType(resourceType))
00184                 {
00185                         NR_Log(Log::LOG_ENGINE, Log::LL_ERROR, "ResourceLoader %s does not support resources of type %s", mName.c_str(), resourceType.c_str());
00186                         return SharedPtr<IResource>();
00187                 }
00188 
00189                 // now check if such a resource is already in the database
00190                 IResourcePtr res = Engine::sResourceManager()->getByName(name);
00191                 if (!res.isNull()){
00192                         NR_Log(Log::LOG_ENGINE, Log::LL_WARNING, "You are trying to create a resource %s of type %s which is already in the database", name.c_str(), resourceType.c_str());
00193                         return SharedPtr<IResource>();
00194                 }
00195 
00196                 // ok now create the resource
00197                 SharedPtr<IResource> r = create(resourceType, params);
00198                 if (r.get() == NULL) return SharedPtr<IResource>();
00199 
00200                 // setup values
00201                 r->mResName = name;
00202                 r->mResGroup = group;
00203 
00204                 // now let manager know about the new resource
00205                 Engine::sResourceManager()->notifyCreated(r.get());
00206 
00207                 return r;
00208         }
00209 #if 0
00210         //----------------------------------------------------------------------------------
00211         Result IResourceLoader::unload(SharedPtr<IResource> resource)
00212         {
00213                 // empty resource could not be unloaded
00214                 if (resource.get() == NULL) return OK;
00215 
00216                 // call the implementation of the unloader
00217                 if (resource->mResIsLoaded){
00218 
00219                         Result ret = unloadResourceImpl(resource.get());
00220                         if (ret != OK) return ret;
00221 
00222                         // now mark the resource that it has been unloaded
00223                         resource->mResIsLoaded = false;
00224 
00225                         // notify the resource manager about unloading the resource
00226                         Engine::sResourceManager()->notifyUnloaded(resource.get());
00227                 }
00228 
00229                 return OK;
00230         }
00231 
00232         //----------------------------------------------------------------------------------
00233         Result IResourceLoader::reload(SharedPtr<IResource> resource)
00234         {
00235                 // check if we are the handler for this resource
00236                 if (std::find(mHandledResources.begin(), mHandledResources.end(), resource) == mHandledResources.end()){
00237                         NR_Log(Log::LOG_ENGINE, Log::LL_WARNING, "ResourceLoader: You are trying to reload resource %s not handled by this loader %s", resource->getResName().c_str(), mName.c_str());
00238                         return OK;
00239                 }
00240 
00241                 // unload the resource
00242                 unload(resource);
00243 
00244                 // call the implementation of the unloader
00245                 if (resource->mResIsLoaded == false)
00246                 {
00247 
00248                         Result ret = reloadResourceImpl(resource.get());
00249                         if (ret != OK) return ret;
00250 
00251                         // now mark the resource that it has been unloaded
00252                         resource->mResIsLoaded = true;
00253 
00254                         // notify the resource manager about unloading the resource
00255                         Engine::sResourceManager()->notifyLoaded(resource.get());
00256                 }
00257 
00258                 return OK;
00259         }
00260 #endif
00261         //----------------------------------------------------------------------------------
00262         Result IResourceLoader::remove(SharedPtr<IResource> resource)
00263         {
00264                 // remove only valid resources
00265                 if (resource.get() == NULL) return OK;
00266 
00267                 // emove only handled resources
00268                 if (std::find(mHandledResources.begin(), mHandledResources.end(), resource) == mHandledResources.end())
00269                 {
00270                         NR_Log(Log::LOG_ENGINE, Log::LL_WARNING, "ResourceLoader: You are trying to remove resource %s not handled by this loader %s!", resource->getResourceName().c_str(), mName.c_str());
00271                         return OK;
00272                 }
00273 
00274                 // unload resource
00275                 resource->unload();
00276 
00277                 // notify to remove the resource
00278                 notifyRemoveResource(resource);
00279 
00280                 // reset the resource, so it gets deleted, if it is not referenced elsewhere
00281                 resource.reset();
00282 
00283                 return OK;
00284         }
00285 
00286         //----------------------------------------------------------------------------------
00287         void IResourceLoader::notifyRemoveResource(SharedPtr<IResource> res)
00288         {
00289                 ResourceList::iterator resit = std::find(mHandledResources.begin(), mHandledResources.end(), res);
00290 
00291                 // check if such resource is loaded
00292                 if (resit != mHandledResources.end() )
00293                 {
00294                         // ok remove the resource from the handled resources
00295                         mHandledResources.erase(resit);
00296 
00297                         // notify the manager about removing the resource
00298                         Engine::sResourceManager()->notifyRemove(res.get());
00299                 }
00300         }
00301 
00302 #if 0
00303 
00304         //----------------------------------------------------------------------------------
00305         void IResourceLoader::notifyUnloadResource(SharedPtr<IResource> res)
00306         {
00307                 if (res == NULL) return;
00308                 if (std::find(mHandledResources.begin(), mHandledResources.end(), res) != mHandledResources.end() && res->mResIsLoaded){
00309                         Engine::sResourceManager()->notifyUnloaded(res.get());
00310                 }
00311         }
00312 
00313         //----------------------------------------------------------------------------------
00314         Result IResourceLoader::unloadResourceImpl(IResource* res)
00315         {
00316                 if (res == NULL) return OK;
00317                 if (res->mResIsLoaded) return res->unloadRes();
00318                 return OK;
00319         }
00320 
00321         //----------------------------------------------------------------------------------
00322         Result IResourceLoader::reloadResourceImpl(IResource* res)
00323         {
00324                 if (res == NULL) return OK;
00325                 /*Result ret = loadResourceImpl(res, res->getResFileName(), NULL);
00326                 if (ret != OK){
00327                         NR_Log(Log::LOG_ENGINE, Log::LL_ERROR, "ResourceLoader %s can not load resource from file %s", mName.c_str(), res->getResFileName().c_str());
00328                         return ret;
00329                 }*/
00330                 if (res->mResIsLoaded == false) res->reloadRes();
00331                 //res->mResIsLoaded = true;
00332 
00333                 // now notify the resource manager, that a new resource was loaded
00334                 //Engine::sResourceManager()->notifyLoaded(res);
00335 
00336                 return OK;
00337         }
00338 #endif
00339         //----------------------------------------------------------------------------------
00340         bool IResourceLoader::supportResourceType(const std::string& resourceType) const {
00341                 std::vector<std::string>::const_iterator it;
00342                 for (it = mSupportedResourceTypes.begin(); it != mSupportedResourceTypes.end(); it++){
00343                         if ((*it) == resourceType) return true;
00344                 }
00345                 return false;
00346         }
00347 
00348         //----------------------------------------------------------------------------------
00349         bool IResourceLoader::supportFileType(const std::string& fileType) const {
00350                 std::vector<std::string>::const_iterator it;
00351                 for (it = mSupportedFileTypes.begin(); it != mSupportedFileTypes.end(); it++){
00352                         if ((*it) == fileType) {
00353                                 return true;
00354                         }
00355                 }
00356                 return false;
00357         }
00358 
00359 };
00360 

Generated on Wed Sep 12 23:19:42 2007 for nrEngine by  doxygen 1.5.1