Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/orxonox/branches/textEngine/src/lib/util/resource_manager.cc @ 3691

Last change on this file since 3691 was 3681, checked in by bensch, 20 years ago

orxonox/branches/textEngine: merged trunk here.
merged with command:
svn merge ../trunk textEngine -r 3467:HEAD
no conflicts

File size: 12.8 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*/
394bool ResourceManager::isDir(const char* directoryName)
395{
396  struct stat status;
397  stat(directoryName, &status);
398  if (status.st_mode & (S_IFDIR | S_IFLNK))
399    return true;
400  else
401    return false;
402}
403
404/**
405   \brief Checks if the file is either a Regular file or a Symlink
406   \param fileName the File to check for
407   \returns true if it is a regular file/symlink, false otherwise
408*/
409bool ResourceManager::isFile(const char* fileName)
410{
411  struct stat status;
412  stat(fileName, &status);
413  if (status.st_mode & (S_IFREG | S_IFLNK))
414    return true;
415  else
416    return false;
417}
418
419/**
420   \brief outputs debug information about the ResourceManager
421*/
422void ResourceManager::debug(void)
423{
424  PRINT(0)("=RM===================================\n");
425  PRINT(0)("= RESOURCE-MANAGER DEBUG INFORMATION =\n");
426  PRINT(0)("======================================\n");
427  // if it is not initialized
428  PRINT(0)(" Reference is: %p\n", ResourceManager::singletonRef);
429  PRINT(0)(" Data-Directory is: %s\n", this->dataDir);
430  PRINT(0)(" List of Image-Directories: ");
431  tIterator<char>* tmpIt = imageDirs->getIterator();
432  char* tmpDir = tmpIt->nextElement();
433  while(tmpDir)
434    {
435      PRINT(0)("%s ",tmpDir);
436      tmpDir = tmpIt->nextElement();
437    }
438  delete tmpIt;
439  PRINT(0)("\n");
440
441  PRINT(0)("List of all stored Resources:\n");
442  tIterator<Resource>* iterator = resourceList->getIterator();
443  Resource* enumRes = iterator->nextElement();
444  while (enumRes)
445    {
446      PRINT(0)("-----------------------------------------\n");
447      PRINT(0)("Name: %s; References: %d; Type:", enumRes->name, enumRes->count);
448      switch (enumRes->type)
449        {
450        case OBJ:
451          PRINT(0)("ObjectModel\n");
452          break;
453        case PRIM:
454          PRINT(0)("PrimitiveModel\n");
455          break;
456        case IMAGE:
457          PRINT(0)("ImageFile (Texture)\n");
458          break;
459        default:
460          PRINT(0)("SoundFile\n");
461          break;
462        }
463      PRINT(0)("gets deleted at ");
464      switch(enumRes->prio)
465        {
466        default:
467        case RP_NO:
468          PRINT(0)("first posibility (0)\n");
469          break;
470        case RP_LEVEL:
471          PRINT(0)("the end of the Level (1)\n");
472          break;
473        case RP_CAMPAIGN:
474          PRINT(0)("the end of the campaign (2)\n");
475          break;
476        case RP_GAME:
477          PRINT(0)("when leaving the game (3)\n");
478          break;
479        }
480      enumRes = iterator->nextElement();
481    }
482  delete iterator;
483
484
485
486  PRINT(0)("==================================RM==\n");
487}
Note: See TracBrowser for help on using the repository browser.