Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/orxonox/branches/levelloader/src/lib/util/resource_manager.cc @ 4102

Last change on this file since 4102 was 3753, checked in by patrick, 20 years ago

branches/levelloader: now compiling again under linux

File size: 13.1 KB
Line 
1/*
2   orxonox - the future of 3D-vertical-scrollers
3
4   Copyright (C) 2004 orx
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, or (at your option)
9   any later version.
10
11   ### File Specific:
12   main-programmer: Benjamin Grauer
13   co-programmer: Patrick Boenzli
14*/
15
16#define DEBUG_SPECIAL_MODULE DEBUG_MODULE_LOAD
17
18#include "resource_manager.h"
19
20// different resource Types
21#include "objModel.h"
22#include "primitive_model.h"
23#include "texture.h"
24
25#include "list.h"
26
27// File Handling Includes
28#include <sys/types.h>
29#include <sys/stat.h>
30#include <unistd.h>
31
32using namespace std;
33
34/**
35   \brief standard constructor
36*/
37ResourceManager::ResourceManager () 
38{
39   this->setClassName ("ResourceManager");
40   this->dataDir = "./";
41   this->imageDirs = new tList<char>();
42   this->resourceList = new tList<Resource>();
43}
44
45/**
46   \returns the Instance to this ResourceManager
47*/
48ResourceManager* ResourceManager::getInstance(void)
49{
50  if (!ResourceManager::singletonRef)
51    ResourceManager::singletonRef = new ResourceManager();
52  return ResourceManager::singletonRef;
53}
54
55//! Singleton Reference to the ResourceManager
56ResourceManager* ResourceManager::singletonRef = NULL;
57
58/**
59   \brief standard destructor
60*/
61ResourceManager::~ResourceManager (void) 
62{
63  // deleting the Resources-List
64  this->unloadAllByPriority(RP_GAME);
65  delete this->resourceList;
66  // deleting the Directorie Lists
67  tIterator<char>* tmpIt = imageDirs->getIterator();
68  char* tmpDir = tmpIt->nextElement();
69  while(tmpDir)
70    {
71      delete []tmpDir;
72      tmpDir = tmpIt->nextElement();
73    }
74  delete tmpIt;
75
76  delete this->imageDirs;
77
78  ResourceManager::singletonRef = NULL;
79}
80
81/**
82   \brief sets the data main directory
83   \param dataDir the DataDirectory.
84*/
85bool ResourceManager::setDataDir(char* dataDir)
86{
87  if (isDir(dataDir))
88    {
89      this->dataDir = new char[strlen(dataDir)+1];
90      strcpy(this->dataDir, dataDir);
91    }
92  else
93    {
94      PRINTF(1)("%s is not a Directory, and can not be the Data Directory\n", dataDir);
95    }
96}
97
98/**
99   \brief adds a new Path for Images
100   \param imageDir The path to insert
101   \returns true, if the Path was well and injected (or already existent within the list)
102   false otherwise
103*/
104bool ResourceManager::addImageDir(char* imageDir)
105{
106  // check if the param is a Directory
107  if (isDir(imageDir))
108    {
109      // check if the Directory has been added before
110      tIterator<char>* tmpImageDirs = imageDirs->getIterator();
111      char* tmpDir = tmpImageDirs->nextElement();
112      while(tmpDir)
113        {
114          if (!strcmp(tmpDir, imageDir))
115            {
116              PRINTF(4)("Path %s already loaded\n", imageDir);
117              delete tmpImageDirs;
118              return true;
119            }
120          tmpDir = tmpImageDirs->nextElement();
121        }
122      delete tmpImageDirs;
123
124      // adding the directory to the List
125      tmpDir  = new char[strlen(imageDir)+1];
126      strcpy(tmpDir, imageDir);
127      this->imageDirs->add(tmpDir);
128      return true;
129    }
130  else
131    {
132      PRINTF(1)("%s is not a Directory, and can not be added to the Paths of Images\n", dataDir);
133      return false;
134    }
135}
136
137/**
138   \brief loads resources
139   \param fileName The fileName of the resource to load
140   \param prio The ResourcePriority of this resource (will only be increased)
141   \returns a pointer to a desired Resource.
142*/
143void* ResourceManager::load(const char* fileName, ResourcePriority prio)
144{
145  ResourceType tmpType;
146  if (!strncmp(fileName+(strlen(fileName)-4), ".obj", 4))
147    tmpType = OBJ;
148  else if (!strncmp(fileName+(strlen(fileName)-4), ".wav", 4))
149    tmpType = WAV;
150  else if (!strncmp(fileName+(strlen(fileName)-4), ".mp3", 4))
151    tmpType = MP3;
152  else if (!strncmp(fileName+(strlen(fileName)-4), ".ogg", 4))
153    tmpType = OGG;
154  else if (!strcmp(fileName, "cube") ||
155           !strcmp(fileName, "sphere") ||
156           !strcmp(fileName, "plane") ||
157           !strcmp(fileName, "cylinder") ||
158           !strcmp(fileName, "cone"))
159    tmpType = PRIM;
160  else 
161    tmpType = IMAGE;
162
163  return this->load(fileName, tmpType, prio);
164}
165
166/**
167   \brief loads resources
168   \param fileName The fileName of the resource to load
169   \param type The Type of Resource to load (\see ResourceType)
170   \param prio The ResourcePriority of this resource (will only be increased)
171   \returns a pointer to a desired Resource.
172*/
173void* ResourceManager::load(const char* fileName, ResourceType type, ResourcePriority prio)
174{
175  // searching if the resource was loaded before.
176  Resource* tmpResource = this->locateResourceByName(fileName);
177  if (tmpResource) // if the resource was not loaded before.
178    {
179      PRINTF(4)("not loading cached resource %s\n", tmpResource->name);
180      tmpResource->count++;
181      if(tmpResource->prio < prio)
182        tmpResource->prio = prio;
183    }
184  else
185    {
186      char* tmpDir;
187      // Setting up the new Resource
188      tmpResource = new Resource;
189      tmpResource->count = 1;
190      tmpResource->type = type;
191      tmpResource->prio = prio;
192      tmpResource->name = new char[strlen(fileName)+1];
193      strcpy(tmpResource->name, fileName);
194
195      // creating the full name. (directoryName + FileName)
196      char* fullName = new char[strlen(dataDir)+strlen(fileName)+1];
197      sprintf(fullName, "%s%s", this->dataDir, fileName);
198     
199      // Checking for the type of resource \see ResourceType
200      switch(type)
201        {
202        case OBJ:
203          if(isFile(fullName))
204            tmpResource->pointer = new OBJModel(fullName);
205          else
206            {
207              PRINTF(2)("Sorry, %s does not exist. Loading a cube-Model instead\n", fullName);
208              tmpResource->pointer = ResourceManager::load("cube", PRIM);
209            }
210          break;
211        case PRIM:
212          if (!strcmp(tmpResource->name, "cube"))
213            tmpResource->pointer = new PrimitiveModel(CUBE);
214          else if (!strcmp(tmpResource->name, "sphere"))
215            tmpResource->pointer = new PrimitiveModel(SPHERE);
216          else if (!strcmp(tmpResource->name, "plane"))
217            tmpResource->pointer = new PrimitiveModel(PLANE);
218          else if (!strcmp(tmpResource->name, "cylinder"))
219            tmpResource->pointer = new PrimitiveModel(CYLINDER);
220          else if (!strcmp(tmpResource->name, "cone"))
221            tmpResource->pointer = new PrimitiveModel(CONE);
222          break;
223        case IMAGE:
224          if(isFile(fullName))
225            {
226              PRINTF(4)("Image %s resides to %s\n", fileName, fullName);
227              tmpResource->pointer = new Texture(fullName);
228            }
229          else
230            {
231              tIterator<char>* iterator = imageDirs->getIterator();
232              tmpDir = iterator->nextElement();
233              //tmpDir = imageDirs->enumerate();
234              while(tmpDir)
235                {
236                  char* imgName = new char[strlen(tmpDir)+strlen(fileName)+1];
237                  sprintf(imgName, "%s%s", tmpDir, fileName);
238                  if(isFile(imgName))
239                    {
240                      PRINTF(4)("Image %s resides to %s\n", fileName, imgName);
241                      tmpResource->pointer = new Texture(imgName);
242                      delete []imgName;
243                      break;
244                    }
245                  delete []imgName;
246                  tmpDir = iterator->nextElement();
247                }
248              delete iterator;
249            }
250          if(!tmpResource)
251             PRINTF(2)("!!Image %s not Found!!\n", fileName);
252          break;
253        default:
254          tmpResource->pointer = NULL;
255          PRINTF(1)("No type found for %s.\n   !!This should not happen unless the Type is not supported yet.!!\n", tmpResource->name);
256          break;
257        }
258      this->resourceList->add(tmpResource);
259      delete []fullName;
260    }
261
262  return tmpResource->pointer;
263}
264
265/**
266   \brief unloads a Resource
267   \param pointer The pointer to free
268   \returns true if successful (pointer found, and deleted), false otherwise
269   
270*/
271bool ResourceManager::unload(void* pointer, ResourcePriority prio)
272{
273  // if pointer is existent. and only one resource of this type exists.
274  Resource* tmpResource = this->locateResourceByPointer(pointer);
275  if (!tmpResource)
276    {
277      PRINTF(2)("Resource not Found %p\n", pointer);
278      return false;
279    }
280  else
281    unload(tmpResource, prio);
282}
283
284bool ResourceManager::unload(Resource* resource, ResourcePriority prio)
285{
286  if (resource->count > 0)
287    resource->count--;
288  if (resource->prio <= prio)
289    {
290      if (resource->count <= 0)
291        {
292          // deleting the Resource
293          switch(resource->type)
294            {
295            case OBJ:
296            case PRIM:
297              delete (Model*)resource->pointer;
298              break;
299            case IMAGE:
300              delete (Texture*)resource->pointer;
301              break;
302            default:
303              PRINTF(1)("NOT YET IMPLEMENTED !!FIX FIX!!\n");
304              return false;
305              break;
306            }
307          // deleting the List Entry:
308          PRINTF(4)("Resource %s safely removed.\n", resource->name);
309          delete []resource->name;
310          this->resourceList->remove(resource);
311        }
312      else
313        PRINTF(4)("Resource %s not removed, because there are still %d References to it.\n", resource->name, resource->count);
314    }
315  else
316    PRINTF(4)("not deleting resource %s because DeleteLevel to high\n", resource->name);
317  return true;
318}
319
320
321/**
322   \brief unloads all alocated Memory of Resources with a pririty lower than prio
323   \param prio The priority to delete
324*/
325bool ResourceManager::unloadAllByPriority(ResourcePriority prio)
326{
327  tIterator<Resource>* iterator = resourceList->getIterator();
328  Resource* enumRes = iterator->nextElement();
329  while (enumRes)
330    {
331      if (enumRes->prio <= prio)
332        if (enumRes->count == 0)
333          unload(enumRes, prio);
334        else
335          PRINTF(2)("unable to unload %s because there are still %d references to it\n",
336                   enumRes->name, enumRes->count);
337      //enumRes = resourceList->nextElement();
338      enumRes = iterator->nextElement();
339    }
340  delete iterator;
341}
342
343/**
344   \brief Searches for a Resource by Name
345   \param fileName The name to look for
346   \returns a Pointer to the Resource if found, NULL otherwise.
347*/
348Resource* ResourceManager::locateResourceByName(const char* fileName)
349{
350  //  Resource* enumRes = resourceList->enumerate();
351  tIterator<Resource>* iterator = resourceList->getIterator();
352  Resource* enumRes = iterator->nextElement();
353  while (enumRes)
354    {
355      if (!strcmp(fileName, enumRes->name))
356        {
357          delete iterator;
358          return enumRes;
359        }
360      enumRes = iterator->nextElement();
361    }
362  delete iterator;
363  return NULL;
364}
365
366/**
367   \brief Searches for a Resource by Pointer
368   \param pointer the Pointer to search for
369   \returns a Pointer to the Resource if found, NULL otherwise.
370*/
371Resource* ResourceManager::locateResourceByPointer(const void* pointer)
372{
373  //  Resource* enumRes = resourceList->enumerate();
374  tIterator<Resource>* iterator = resourceList->getIterator();
375  Resource* enumRes = iterator->nextElement();
376  while (enumRes)
377    {
378      if (pointer == enumRes->pointer)
379        {
380          delete iterator;
381          return enumRes;
382        }
383      enumRes = iterator->nextElement();
384    }
385  delete iterator;
386  return NULL;
387}
388
389/**
390   \brief Checks if it is a Directory
391   \param directoryName the Directory to check for
392   \returns true if it is a directory/symlink false otherwise
393   \todo implement for win32 usage too
394   \bug does return false by default on win32
395*/
396bool ResourceManager::isDir(const char* directoryName)
397{
398#ifdef __WIN32__
399  return false;
400#elif __unix__
401  struct stat status;
402  stat(directoryName, &status);
403  if (status.st_mode & (S_IFDIR | S_IFLNK))
404    return true;
405  else
406    return false;
407#endif
408}
409
410/**
411   \brief Checks if the file is either a Regular file or a Symlink
412   \param fileName the File to check for
413   \returns true if it is a regular file/symlink, false otherwise
414   \todo implement fo win32 usage too
415   \bug does return false by default on win32
416*/
417bool ResourceManager::isFile(const char* fileName)
418{
419#ifdef __WIN32__
420  return false;
421#elif __unix__
422  struct stat status;
423  stat(fileName, &status);
424  if (status.st_mode & (S_IFREG | S_IFLNK))
425    return true;
426  else
427    return false;
428#endif
429}
430
431/**
432   \brief outputs debug information about the ResourceManager
433*/
434void ResourceManager::debug(void)
435{
436  PRINT(0)("=RM===================================\n");
437  PRINT(0)("= RESOURCE-MANAGER DEBUG INFORMATION =\n");
438  PRINT(0)("======================================\n");
439  // if it is not initialized
440  PRINT(0)(" Reference is: %p\n", ResourceManager::singletonRef);
441  PRINT(0)(" Data-Directory is: %s\n", this->dataDir);
442  PRINT(0)(" List of Image-Directories: ");
443  tIterator<char>* tmpIt = imageDirs->getIterator();
444  char* tmpDir = tmpIt->nextElement();
445  while(tmpDir)
446    {
447      PRINT(0)("%s ",tmpDir);
448      tmpDir = tmpIt->nextElement();
449    }
450  delete tmpIt;
451  PRINT(0)("\n");
452
453  PRINT(0)("List of all stored Resources:\n");
454  tIterator<Resource>* iterator = resourceList->getIterator();
455  Resource* enumRes = iterator->nextElement();
456  while (enumRes)
457    {
458      PRINT(0)("-----------------------------------------\n");
459      PRINT(0)("Name: %s; References: %d; Type:", enumRes->name, enumRes->count);
460      switch (enumRes->type)
461        {
462        case OBJ:
463          PRINT(0)("ObjectModel\n");
464          break;
465        case PRIM:
466          PRINT(0)("PrimitiveModel\n");
467          break;
468        case IMAGE:
469          PRINT(0)("ImageFile (Texture)\n");
470          break;
471        default:
472          PRINT(0)("SoundFile\n");
473          break;
474        }
475      PRINT(0)("gets deleted at ");
476      switch(enumRes->prio)
477        {
478        default:
479        case RP_NO:
480          PRINT(0)("first posibility (0)\n");
481          break;
482        case RP_LEVEL:
483          PRINT(0)("the end of the Level (1)\n");
484          break;
485        case RP_CAMPAIGN:
486          PRINT(0)("the end of the campaign (2)\n");
487          break;
488        case RP_GAME:
489          PRINT(0)("when leaving the game (3)\n");
490          break;
491        }
492      enumRes = iterator->nextElement();
493    }
494  delete iterator;
495
496
497
498  PRINT(0)("==================================RM==\n");
499}
Note: See TracBrowser for help on using the repository browser.