source: nrEngine/src/ResourceLoader.cpp @ 15

Revision 15, 11.9 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<SharedPtr<IResource> > lst;
36                for (ResourceList::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        SharedPtr<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 SharedPtr<IResource>();
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 SharedPtr<IResource>();
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 SharedPtr<IResource>();
81                        }
82                }
83               
84                // ok the name is supported, so now create a instance
85                SharedPtr<IResource> res;
86                if (resourceType.length() == 0){
87                        res = create(mapFileTypeToResourceType(type), param);
88                }else{
89                        res = create(resourceType, param);
90                }
91                if (res.get() == NULL) return res;
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 (loadResourceImpl(res.get(), 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 SharedPtr<IResource>();
104                }
105                res->mResIsLoaded = true;
106
107                // now notify the resource manager, that a new resource was loaded
108                Engine::sResourceManager()->notifyLoaded(res.get());
109
110                return res;
111        }
112
113        //----------------------------------------------------------------------------------
114        SharedPtr<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 SharedPtr<IResource>();
123                }
124
125                // now call the implemented function to create the resource
126                SharedPtr<IResource> res (createResourceImpl(resourceType, params), IResource::_deleter());
127
128                // check if the result is valid, then add it into our database
129                if (res.get() == NULL) return SharedPtr<IResource>();
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( createEmptyResource(resourceType), IResource::_deleter() );
137                        empty->mResGroup = "_Empty_Resource_Group_";
138                        empty->mResName = "_Empty_" + resourceType;
139                        empty->mResHandle = Engine::sResourceManager()->getNewHandle();
140                        empty->mResIsEmpty = true;
141                        empty->mResLoader = getSharedPtrFromThis();
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->mResIsEmpty = false;
152                res->mResLoader = getSharedPtrFromThis();
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        SharedPtr<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 SharedPtr<IResource>();
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 SharedPtr<IResource>();
176                }
177
178                // ok now create the resource
179                SharedPtr<IResource> r = create(resourceType, params);
180                if (r.get() == NULL) return SharedPtr<IResource>();
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.get());
188
189                return r;
190        }
191
192        //----------------------------------------------------------------------------------
193        Result IResourceLoader::unload(SharedPtr<IResource> resource)
194        {
195                // empty resource could not be unloaded
196                if (resource.get() == NULL) return OK;
197
198                // call the implementation of the unloader
199                if (resource->mResIsLoaded){
200                       
201                        Result ret = unloadResourceImpl(resource.get());
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.get());
209                }
210               
211                return OK;
212        }
213
214        //----------------------------------------------------------------------------------
215        Result IResourceLoader::reload(SharedPtr<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 reloadResourceImpl(resource.get());
228        }
229
230        //----------------------------------------------------------------------------------
231        Result IResourceLoader::remove(SharedPtr<IResource> resource)
232        {
233                // remove only valid resources
234                if (resource.get() == NULL) return OK;
235
236                // emove only handled resources
237                if (std::find(mHandledResources.begin(), mHandledResources.end(), resource) == mHandledResources.end())
238                {
239                        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());
240                        return OK;
241                }
242
243                // unload
244                unload(resource);
245               
246                // notify to remove the resource
247                notifyRemoveResource(resource);
248
249                // reset the resource, so it gets deleted, if it is not referenced elsewhere
250                resource.reset();
251
252                return OK;
253        }
254
255        //----------------------------------------------------------------------------------
256        void IResourceLoader::notifyRemoveResource(SharedPtr<IResource> res)
257        {
258                ResourceList::iterator resit = std::find(mHandledResources.begin(), mHandledResources.end(), res);
259               
260                // check if such resource is loaded
261                if (resit != mHandledResources.end() ){
262               
263                        // ok remove the resource from the handled resources
264                        mHandledResources.erase(resit);
265
266                        // notify the manager about removing the resource
267                        Engine::sResourceManager()->notifyRemove(res.get());
268                }
269        }
270
271        //----------------------------------------------------------------------------------
272        void IResourceLoader::notifyUnloadResource(SharedPtr<IResource> res)
273        {
274                if (res == NULL) return;
275                if (std::find(mHandledResources.begin(), mHandledResources.end(), res) != mHandledResources.end() && res->mResIsLoaded){
276                        Engine::sResourceManager()->notifyUnloaded(res.get());
277                }
278        }
279
280        //----------------------------------------------------------------------------------
281        Result IResourceLoader::unloadResourceImpl(IResource* res)
282        {
283                if (res == NULL) return OK;
284                if (res->mResIsLoaded) return res->unloadRes();
285                return OK;
286        }
287
288        //----------------------------------------------------------------------------------
289        Result IResourceLoader::reloadResourceImpl(IResource* res)
290        {
291                if (res == NULL) return OK;
292                Result ret = loadResourceImpl(res, res->getResFileName(), NULL);
293                if (ret != OK){
294                        NR_Log(Log::LOG_ENGINE, Log::LL_ERROR, "ResourceLoader %s can not load resource from file %s", mName.c_str(), res->getResFileName().c_str());
295                        return ret;
296                }
297                res->mResIsLoaded = true;
298
299                // now notify the resource manager, that a new resource was loaded
300                Engine::sResourceManager()->notifyLoaded(res);
301                               
302                return ret;
303        }
304       
305        //----------------------------------------------------------------------------------
306        bool IResourceLoader::supportResourceType(const std::string& resourceType) const {
307                std::vector<std::string>::const_iterator it;
308                for (it = mSupportedResourceTypes.begin(); it != mSupportedResourceTypes.end(); it++){
309                        if ((*it) == resourceType) return true;
310                }
311                return false;
312        }
313
314        //----------------------------------------------------------------------------------
315        bool IResourceLoader::supportFileType(const std::string& fileType) const {
316                std::vector<std::string>::const_iterator it;
317                for (it = mSupportedFileTypes.begin(); it != mSupportedFileTypes.end(); it++){
318                        if ((*it) == fileType) {
319                                return true;
320                        }
321                }
322                return false;
323        }
324       
325};
326
Note: See TracBrowser for help on using the repository browser.