source: nrEngine/src/ResourceLoader.cpp @ 1

Revision 1, 11.4 KB checked in by art, 13 years ago (diff)
Line 
1/***************************************************************************
2 *                                                                         *
3 *   (c) Art Tevs, MPI Informatik Saarbruecken                             *
4 *       mailto: <tevs@mpi-sb.mpg.de>                                      *
5 *                                                                         *
6 *   This program is free software; you can redistribute it and/or modify  *
7 *   it under the terms of the GNU General Public License as published by  *
8 *   the Free Software Foundation; either version 2 of the License, or     *
9 *   (at your option) any later version.                                   *
10 *                                                                         *
11 ***************************************************************************/
12
13
14//----------------------------------------------------------------------------------
15// Includes
16//----------------------------------------------------------------------------------
17#include "ResourceLoader.h"
18#include "Log.h"
19#include "Exception.h"
20#include "Engine.h"
21#include "ResourceManager.h"
22
23namespace nrEngine{
24       
25        //----------------------------------------------------------------------------------
26        IResourceLoader::IResourceLoader(const std::string& name) : mName(name)
27        {
28
29        }
30
31        //----------------------------------------------------------------------------------
32        IResourceLoader::~IResourceLoader()
33        {
34                // copy the list in another list, so we can iterate and remove them
35                std::vector<IResource*> lst;
36                for (std::list<IResource*>::iterator it = mHandledResources.begin(); it != mHandledResources.end(); it ++)
37                        lst.push_back(*it);
38
39                // now go through the vector and remove elements
40                for (uint32 i=0; i < lst.size(); i++)
41                        remove(lst[i]);
42        }
43
44        //----------------------------------------------------------------------------------
45        IResource* IResourceLoader::load(const std::string& name, const std::string& group, const std::string& fileName, const std::string& resourceType, PropertyList* param)
46        {
47                // check if a such resource already registered by the manager
48                if (Engine::sResourceManager()->isResourceRegistered(name))
49                {
50                        NR_Log(Log::LOG_ENGINE, Log::LL_ERROR, "ResourceLoader: You are trying to load resource %s which is already loaded.", name.c_str());
51                        return NULL;
52                }
53               
54                bool typeFound = false;
55                std::string type;
56               
57                // we search for the type if no type is specified
58                if (resourceType.length() == 0){
59                        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());
60                       
61                        // detect the file type by reading out it's last characters
62                        for (int32 i = fileName.length()-1; i >= 0 && !typeFound; i--){
63                                if ((char)fileName[i] == '.'){
64                                        typeFound = true;
65                                }
66                                if (!typeFound) type = (char)fileName[i] + type;
67                        }
68                        if (!typeFound) type = "";
69                       
70                        // check whenever the given file name is supported by the resource
71                        if (typeFound && !supportFileType(type))
72                        {
73                                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());
74                                return NULL;
75                        }
76
77                        // if no type was specified so give up
78                        if (!typeFound){
79                                NR_Log(Log::LOG_ENGINE, Log::LL_ERROR, "ResourceLoader %s neither resource type nor valid file ending was found, give up!", mName.c_str());
80                                return NULL;
81                        }
82                }
83               
84                // ok the name is supported, so now create a instance
85                IResource* res = NULL;
86                if (resourceType.length() == 0){
87                        res = create(mapFileTypeToResourceType(type), param);
88                }else{
89                        res = create(resourceType, param);
90                }
91                if (res == NULL) return NULL;
92               
93                // setup some data on resource
94                res->mResFileName = fileName;
95                res->mResName = name;
96                res->mResGroup = group;
97
98                // now call the implemented loading function
99                if (loadImpl(res, fileName, param) != OK)
100                {
101                        NR_Log(Log::LOG_ENGINE, Log::LL_ERROR, "ResourceLoader %s can not load resource from file %s", mName.c_str(), fileName.c_str());
102                        remove(res);
103                        return NULL;
104                }
105                res->mResIsLoaded = true;
106
107                // now notify the resource manager, that a new resource was loaded
108                Engine::sResourceManager()->notifyLoaded(res);
109
110                return res;
111        }
112
113        //----------------------------------------------------------------------------------
114        IResource* IResourceLoader::create(const std::string& resourceType, PropertyList* params)
115        {
116                NR_Log(Log::LOG_ENGINE, Log::LL_DEBUG, "ResourceLoader: Create resource of type %s", resourceType.c_str());
117               
118                // first check if this type of resource is supported
119                if (!supportResourceType(resourceType))
120                {
121                        NR_Log(Log::LOG_ENGINE, Log::LL_ERROR, "ResourceLoader %s does not support resources of type %s", mName.c_str(), resourceType.c_str());
122                        return NULL;
123                }
124
125                // now call the implemented function to create the resource
126                IResource* res = (createImpl(resourceType, params));
127
128                // check if the result is valid, then add it into our database
129                if (res == NULL) return NULL;
130
131                // now check if we have to create an empty resource for this type
132                SharedPtr<IResource> empty = Engine::sResourceManager()->getEmpty(resourceType);
133                               
134                // if not created before, so create it and register by the manager
135                if (empty == NULL){
136                        empty.reset( createEmpty(resourceType) );
137                        empty->mResGroup = "_Empty_Resource_Group_";
138                        empty->mResName = "_Empty_" + resourceType;
139                        empty->mResHandle = Engine::sResourceManager()->getNewHandle();
140                        empty->mResLoader = this;
141                        empty->mResIsEmpty = true;
142                        empty->setResourceType(resourceType);
143                }
144               
145                // set the resource in the manager
146                Engine::sResourceManager()->setEmpty(resourceType, empty);
147               
148                // setup default resource data
149                res->setResourceType(resourceType);
150                res->mResHandle = Engine::sResourceManager()->getNewHandle();
151                res->mResLoader = this;
152                res->mResIsEmpty = false;
153
154                // now set this resource in the list of handled resource objects
155                mHandledResources.push_back(res);
156               
157                // ok now return the instance
158                return res;
159        }
160
161        //----------------------------------------------------------------------------------
162        IResource* IResourceLoader::create(const std::string& name, const std::string& group, const std::string& resourceType, PropertyList* params)
163        {
164                // first check if this type of resource is supported
165                if (!supportResourceType(resourceType))
166                {
167                        NR_Log(Log::LOG_ENGINE, Log::LL_ERROR, "ResourceLoader %s does not support resources of type %s", mName.c_str(), resourceType.c_str());
168                        return NULL;
169                }
170
171                // now check if such a resource is already in the database
172                IResourcePtr res = Engine::sResourceManager()->getByName(name);
173                if (!res.isNull()){
174                        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());
175                        return NULL;
176                }
177
178                // ok now create the resource
179                IResource* r = create(resourceType, params);
180                if (r == NULL) return NULL;
181
182                // setup values
183                r->mResName = name;
184                r->mResGroup = group;
185               
186                // now let manager know about the new resource
187                Engine::sResourceManager()->notifyCreated(r);
188
189                return r;
190        }
191
192        //----------------------------------------------------------------------------------
193        Result IResourceLoader::unload(IResource* resource)
194        {
195                // empty resource could not be unloaded
196                if (resource == NULL) return OK;
197
198                // call the implementation of the unloader
199                if (resource->mResIsLoaded){
200                       
201                        Result ret = unloadImpl(resource);
202                        if (ret != OK) return ret;
203               
204                        // now mark the resource that it has been unloaded
205                        resource->mResIsLoaded = false;
206                       
207                        // notify the resource manager about unloading the resource
208                        Engine::sResourceManager()->notifyUnloaded(resource);
209                }
210               
211                return OK;
212        }
213
214        //----------------------------------------------------------------------------------
215        Result IResourceLoader::reload(IResource* resource)
216        {
217                // check if we are the handler for this resource
218                if (std::find(mHandledResources.begin(), mHandledResources.end(), resource) == mHandledResources.end()){
219                        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());
220                        return OK;
221                }
222               
223                // unload the resource
224                unload(resource);
225
226                // now reload the resource and go back
227                return reloadImpl(resource);
228        }
229
230        //----------------------------------------------------------------------------------
231        Result IResourceLoader::remove(IResource* resource)
232        {
233                // remove only valid resources
234                if (resource == NULL) return OK;
235
236                // emove only handled resources
237                if (std::find(mHandledResources.begin(), mHandledResources.end(), resource) == mHandledResources.end()){
238                        NR_Log(Log::LOG_ENGINE, Log::LL_WARNING, "ResourceLoader: You are trying to remove resource %s not handled by this loader %s!", resource->getResName().c_str(), mName.c_str());
239                        return OK;
240                }
241
242                // unload
243                unload(resource);
244               
245                // notify to remove the resource
246                notifyRemoveResource(resource);
247
248                // delete the resource object, so it get's removed
249                delete resource;
250
251                return OK;
252        }
253
254        //----------------------------------------------------------------------------------
255        void IResourceLoader::notifyRemoveResource(IResource* res)
256        {
257                // check if such resource is loaded
258                if (std::find(mHandledResources.begin(), mHandledResources.end(), res) != mHandledResources.end() ){
259                        // ok remove the resource from the handled resources
260                        mHandledResources.erase(std::find(mHandledResources.begin(), mHandledResources.end(), res));
261
262                        // notify the manager about removing the resource
263                        Engine::sResourceManager()->notifyRemove(res);
264                }
265        }
266
267        //----------------------------------------------------------------------------------
268        void IResourceLoader::notifyUnloadResource(IResource* res)
269        {
270                if (res == NULL) return;
271                if (std::find(mHandledResources.begin(), mHandledResources.end(), res) != mHandledResources.end() && res->mResIsLoaded){
272                        Engine::sResourceManager()->notifyUnloaded(res);
273                }
274        }
275
276        //----------------------------------------------------------------------------------
277        Result IResourceLoader::unloadImpl(IResource* res)
278        {
279                if (res == NULL) return OK;
280                if (res->mResIsLoaded) 
281                        return res->unloadRes();
282                return OK;
283        }
284
285        //----------------------------------------------------------------------------------
286        Result IResourceLoader::reloadImpl(IResource* res)
287        {
288                if (res == NULL) return OK;
289                Result ret = loadImpl(res, res->getResFileName(), NULL);
290                if (ret != OK){
291                        NR_Log(Log::LOG_ENGINE, Log::LL_ERROR, "ResourceLoader %s can not load resource from file %s", mName.c_str(), res->getResFileName().c_str());
292                        return ret;
293                }
294                res->mResIsLoaded = true;
295
296                // now notify the resource manager, that a new resource was loaded
297                Engine::sResourceManager()->notifyLoaded(res);
298                               
299                return ret;
300        }
301       
302        //----------------------------------------------------------------------------------
303        bool IResourceLoader::supportResourceType(const std::string& resourceType) const {
304                std::vector<std::string>::const_iterator it;
305                for (it = mSupportedResourceTypes.begin(); it != mSupportedResourceTypes.end(); it++){
306                        if ((*it) == resourceType) return true;
307                }
308                return false;
309        }
310
311        //----------------------------------------------------------------------------------
312        bool IResourceLoader::supportFileType(const std::string& fileType) const {
313                std::vector<std::string>::const_iterator it;
314                for (it = mSupportedFileTypes.begin(); it != mSupportedFileTypes.end(); it++){
315                        if ((*it) == fileType) {
316                                return true;
317                        }
318                }
319                return false;
320        }
321       
322};
323
Note: See TracBrowser for help on using the repository browser.