source: nrEngine/src/ResourceLoader.cpp @ 32

Revision 32, 12.5 KB checked in by art, 12 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                std::string newFileName = fileName;
57               
58                // we search for the type if no type is specified
59                if (resourceType.length() == 0)
60                {
61                        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());
62
63                        // detect the file type by reading out it's last characters
64                        for (int32 i = fileName.length()-1; i >= 0 && !typeFound; i--){
65                                if ((char)fileName[i] == '.'){
66                                        typeFound = true;
67                                }
68                                if (!typeFound) type = (char)fileName[i] + type;
69                        }
70                        if (!typeFound) type = "";
71
72                        // check whenever the given file name is supported by the resource
73                        if (typeFound && !supportFileType(type))
74                        {
75                                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());
76                                return SharedPtr<IResource>();
77                        }
78
79                        // if no type foud, then check if suffix is defined
80                        if (!typeFound && resourceType.length() > 0)
81                        {
82                                type = getSuffix(resourceType);
83                                if (type.length() > 0)
84                                {       
85                                        typeFound = true;
86                                        newFileName = fileName + std::string(".") + type;
87                                }
88                        }
89                       
90                        // if no type was specified so give up
91                        if (!typeFound)
92                        {
93                                NR_Log(Log::LOG_ENGINE, Log::LL_ERROR, "ResourceLoader %s: neither resource type nor valid file ending was found, give up!", mName.c_str());
94                                return SharedPtr<IResource>();
95                        }
96                }
97
98                // ok the name is supported, so now create a instance
99                SharedPtr<IResource> res;
100                if (resourceType.length() == 0){
101                        res = create(mapFileTypeToResourceType(type), param);
102                }else{
103                        res = create(resourceType, param);
104                }
105                if (res.get() == NULL) return res;
106
107                // setup some data on resource
108                res->addResourceFilename(newFileName);
109                res->mResName = name;
110                res->mResGroup = group;
111
112                // now call the implemented loading function
113                if (loadResourceImpl(res.get(), newFileName, param) != OK)
114                {
115                        NR_Log(Log::LOG_ENGINE, Log::LL_ERROR, "ResourceLoader %s can not load resource from file %s", mName.c_str(), newFileName.c_str());
116                        remove(res);
117                        return SharedPtr<IResource>();
118                }
119                res->mResIsLoaded = true;
120
121                // now notify the resource manager, that a new resource was loaded
122                Engine::sResourceManager()->notifyLoaded(res.get());
123
124                return res;
125        }
126
127        //----------------------------------------------------------------------------------
128        SharedPtr<IResource> IResourceLoader::create(const std::string& resourceType, PropertyList* params)
129        {
130                NR_Log(Log::LOG_ENGINE, Log::LL_DEBUG, "ResourceLoader: Create resource of type %s", resourceType.c_str());
131
132                // first check if this type of resource is supported
133                if (!supportResourceType(resourceType))
134                {
135                        NR_Log(Log::LOG_ENGINE, Log::LL_ERROR, "ResourceLoader %s does not support resources of type %s", mName.c_str(), resourceType.c_str());
136                        return SharedPtr<IResource>();
137                }
138
139                // now call the implemented function to create the resource
140                SharedPtr<IResource> res (createResourceImpl(resourceType, params), IResource::_deleter());
141
142                // check if the result is valid, then add it into our database
143                if (res.get() == NULL) return SharedPtr<IResource>();
144
145                // now check if we have to create an empty resource for this type
146                SharedPtr<IResource> empty = Engine::sResourceManager()->getEmpty(resourceType);
147
148                // if not created before, so create it and register by the manager
149                if (empty == NULL)
150                {
151                        empty.reset( createEmptyResource(resourceType), IResource::_deleter() );
152                        empty->mResGroup = "_Empty_Resource_Group_";
153                        empty->mResName = "_Empty_" + resourceType;
154                        empty->mResHandle = Engine::sResourceManager()->getNewHandle();
155                        empty->mResIsEmpty = true;
156                        empty->mResLoader = getSharedPtrFromThis();
157                        empty->setResourceType(resourceType);
158                }
159
160                // set the resource in the manager
161                Engine::sResourceManager()->setEmpty(resourceType, empty);
162
163                // setup default resource data
164                res->setResourceType(resourceType);
165                res->mResHandle = Engine::sResourceManager()->getNewHandle();
166                res->mResIsEmpty = false;
167                res->mResLoader = getSharedPtrFromThis();
168
169                // now set this resource in the list of handled resource objects
170                mHandledResources.push_back(res);
171
172                // ok now return the instance
173                return res;
174        }
175
176        //----------------------------------------------------------------------------------
177        SharedPtr<IResource> IResourceLoader::create(const std::string& name, const std::string& group, const std::string& resourceType, PropertyList* params)
178        {
179                // first check if this type of resource is supported
180                if (!supportResourceType(resourceType))
181                {
182                        NR_Log(Log::LOG_ENGINE, Log::LL_ERROR, "ResourceLoader %s does not support resources of type %s", mName.c_str(), resourceType.c_str());
183                        return SharedPtr<IResource>();
184                }
185
186                // now check if such a resource is already in the database
187                IResourcePtr res = Engine::sResourceManager()->getByName(name);
188                if (!res.isNull()){
189                        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());
190                        return SharedPtr<IResource>();
191                }
192
193                // ok now create the resource
194                SharedPtr<IResource> r = create(resourceType, params);
195                if (r.get() == NULL) return SharedPtr<IResource>();
196
197                // setup values
198                r->mResName = name;
199                r->mResGroup = group;
200
201                // now let manager know about the new resource
202                Engine::sResourceManager()->notifyCreated(r.get());
203
204                return r;
205        }
206
207        //----------------------------------------------------------------------------------
208        Result IResourceLoader::unload(SharedPtr<IResource> resource)
209        {
210                // empty resource could not be unloaded
211                if (resource.get() == NULL) return OK;
212
213                // call the implementation of the unloader
214                if (resource->mResIsLoaded){
215
216                        Result ret = unloadResourceImpl(resource.get());
217                        if (ret != OK) return ret;
218
219                        // now mark the resource that it has been unloaded
220                        resource->mResIsLoaded = false;
221
222                        // notify the resource manager about unloading the resource
223                        Engine::sResourceManager()->notifyUnloaded(resource.get());
224                }
225
226                return OK;
227        }
228
229        //----------------------------------------------------------------------------------
230        Result IResourceLoader::reload(SharedPtr<IResource> resource)
231        {
232                // check if we are the handler for this resource
233                if (std::find(mHandledResources.begin(), mHandledResources.end(), resource) == mHandledResources.end()){
234                        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());
235                        return OK;
236                }
237
238                // unload the resource
239                unload(resource);
240
241                // call the implementation of the unloader
242                if (resource->mResIsLoaded == false)
243                {
244
245                        Result ret = reloadResourceImpl(resource.get());
246                        if (ret != OK) return ret;
247
248                        // now mark the resource that it has been unloaded
249                        resource->mResIsLoaded = true;
250
251                        // notify the resource manager about unloading the resource
252                        Engine::sResourceManager()->notifyLoaded(resource.get());
253                }
254
255                return OK;
256        }
257
258        //----------------------------------------------------------------------------------
259        Result IResourceLoader::remove(SharedPtr<IResource> resource)
260        {
261                // remove only valid resources
262                if (resource.get() == NULL) return OK;
263
264                // emove only handled resources
265                if (std::find(mHandledResources.begin(), mHandledResources.end(), resource) == mHandledResources.end())
266                {
267                        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());
268                        return OK;
269                }
270
271                // unload
272                unload(resource);
273
274                // notify to remove the resource
275                notifyRemoveResource(resource);
276
277                // reset the resource, so it gets deleted, if it is not referenced elsewhere
278                resource.reset();
279
280                return OK;
281        }
282
283        //----------------------------------------------------------------------------------
284        void IResourceLoader::notifyRemoveResource(SharedPtr<IResource> res)
285        {
286                ResourceList::iterator resit = std::find(mHandledResources.begin(), mHandledResources.end(), res);
287
288                // check if such resource is loaded
289                if (resit != mHandledResources.end() ){
290
291                        // ok remove the resource from the handled resources
292                        mHandledResources.erase(resit);
293
294                        // notify the manager about removing the resource
295                        Engine::sResourceManager()->notifyRemove(res.get());
296                }
297        }
298
299        //----------------------------------------------------------------------------------
300        void IResourceLoader::notifyUnloadResource(SharedPtr<IResource> res)
301        {
302                if (res == NULL) return;
303                if (std::find(mHandledResources.begin(), mHandledResources.end(), res) != mHandledResources.end() && res->mResIsLoaded){
304                        Engine::sResourceManager()->notifyUnloaded(res.get());
305                }
306        }
307
308        //----------------------------------------------------------------------------------
309        Result IResourceLoader::unloadResourceImpl(IResource* res)
310        {
311                if (res == NULL) return OK;
312                if (res->mResIsLoaded) return res->unloadRes();
313                return OK;
314        }
315
316        //----------------------------------------------------------------------------------
317        Result IResourceLoader::reloadResourceImpl(IResource* res)
318        {
319                if (res == NULL) return OK;
320                /*Result ret = loadResourceImpl(res, res->getResFileName(), NULL);
321                if (ret != OK){
322                        NR_Log(Log::LOG_ENGINE, Log::LL_ERROR, "ResourceLoader %s can not load resource from file %s", mName.c_str(), res->getResFileName().c_str());
323                        return ret;
324                }*/
325                if (res->mResIsLoaded == false) res->reloadRes();
326                //res->mResIsLoaded = true;
327
328                // now notify the resource manager, that a new resource was loaded
329                //Engine::sResourceManager()->notifyLoaded(res);
330
331                return OK;
332        }
333
334        //----------------------------------------------------------------------------------
335        bool IResourceLoader::supportResourceType(const std::string& resourceType) const {
336                std::vector<std::string>::const_iterator it;
337                for (it = mSupportedResourceTypes.begin(); it != mSupportedResourceTypes.end(); it++){
338                        if ((*it) == resourceType) return true;
339                }
340                return false;
341        }
342
343        //----------------------------------------------------------------------------------
344        bool IResourceLoader::supportFileType(const std::string& fileType) const {
345                std::vector<std::string>::const_iterator it;
346                for (it = mSupportedFileTypes.begin(); it != mSupportedFileTypes.end(); it++){
347                        if ((*it) == fileType) {
348                                return true;
349                        }
350                }
351                return false;
352        }
353
354};
355
Note: See TracBrowser for help on using the repository browser.