Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/orxonox/trunk/src/lib/util/resource_manager.cc @ 3672

Last change on this file since 3672 was 3672, checked in by bensch, 19 years ago

orxonox/trunk: ResourceManager not totally static anymore, list-iterators, and so on

File size: 11.0 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      char* tmpDir;
180      // Setting up the new Resource
181      tmpResource = new Resource;
182      tmpResource->count = 1;
183      tmpResource->type = type;
184      tmpResource->prio = prio;
185      tmpResource->name = new char[strlen(fileName)+1];
186      strcpy(tmpResource->name, fileName);
187
188      // creating the full name. (directoryName + FileName)
189      char* fullName = new char[strlen(dataDir)+strlen(fileName)+1];
190      sprintf(fullName, "%s%s", this->dataDir, fileName);
191     
192      // Checking for the type of resource \see ResourceType
193      switch(type)
194        {
195        case OBJ:
196          if(isFile(fullName))
197            tmpResource->pointer = new OBJModel(fullName);
198          else
199            {
200              PRINTF(2)("Sorry, %s does not exist. Loading a cube-Model instead\n", fullName);
201              tmpResource->pointer = ResourceManager::load("cube", PRIM);
202            }
203          break;
204        case PRIM:
205          if (!strcmp(tmpResource->name, "cube"))
206            tmpResource->pointer = new PrimitiveModel(CUBE);
207          else if (!strcmp(tmpResource->name, "sphere"))
208            tmpResource->pointer = new PrimitiveModel(SPHERE);
209          else if (!strcmp(tmpResource->name, "plane"))
210            tmpResource->pointer = new PrimitiveModel(PLANE);
211          else if (!strcmp(tmpResource->name, "cylinder"))
212            tmpResource->pointer = new PrimitiveModel(CYLINDER);
213          else if (!strcmp(tmpResource->name, "cone"))
214            tmpResource->pointer = new PrimitiveModel(CONE);
215          break;
216        case IMAGE:
217          if(isFile(fullName))
218            {
219              tmpResource->pointer = new Texture(fullName);
220            }
221          else
222            {
223              tIterator<char>* iterator = imageDirs->getIterator();
224              tmpDir = iterator->nextElement();
225              //tmpDir = imageDirs->enumerate();
226              while(tmpDir)
227                {
228                  char* imgName = new char[strlen(tmpDir)+strlen(fileName)+1];
229                  sprintf(imgName, "%s%s", tmpDir, fileName);
230                  if(isFile(imgName))
231                    tmpResource->pointer = new Texture(imgName);
232                  delete []imgName;
233                  tmpDir = iterator->nextElement();
234                }
235              delete iterator;
236            }
237          if(!tmpResource)
238             PRINTF(2)("!!Image %s not Found!!\n", fileName);
239          break;
240        default:
241          tmpResource->pointer = NULL;
242          PRINTF(1)("No type found for %s.\n   !!This should not happen unless the Type is not supported yet.!!\n", tmpResource->name);
243          break;
244        }
245     
246      // checking if the File really exists.
247      if(!isFile(fullName))
248        {
249          PRINTF(2)("Sorry, %s is not a regular file.\n", fullName);
250          tmpResource->pointer = NULL;
251        }
252      this->resourceList->add(tmpResource);
253      delete []fullName;
254    }
255  else
256    {
257      PRINTF(4)("not loading cached resource %s\n", tmpResource->name);
258      tmpResource->count++;
259      if(tmpResource->prio < prio)
260        tmpResource->prio = prio;
261    }
262
263  return tmpResource->pointer;
264}
265
266/**
267   \brief unloads a Resource
268   \param pointer The pointer to free
269   \returns true if successful (pointer found, and deleted), false otherwise
270   
271*/
272bool ResourceManager::unload(void* pointer, ResourcePriority prio)
273{
274  // if pointer is existent. and only one resource of this type exists.
275  Resource* tmpResource = this->locateResourceByPointer(pointer);
276  if (!tmpResource)
277    {
278      PRINTF(2)("Resource not Found %p\n", pointer);
279      return false;
280    }
281  else
282    unload(tmpResource, prio);
283}
284
285bool ResourceManager::unload(Resource* resource, ResourcePriority prio)
286{
287  if (resource->count > 0)
288    resource->count--;
289  if (resource->prio <= prio)
290    {
291      if (resource->count <= 0)
292        {
293          // deleting the Resource
294          switch(resource->type)
295            {
296            case OBJ:
297            case PRIM:
298              delete (Model*)resource->pointer;
299              break;
300            case IMAGE:
301              delete (Texture*)resource->pointer;
302              break;
303            default:
304              PRINTF(1)("NOT YET IMPLEMENTED !!FIX FIX!!\n");
305              return false;
306              break;
307            }
308          // deleting the List Entry:
309          PRINTF(4)("Resource %s safely removed.\n", resource->name);
310          delete []resource->name;
311          this->resourceList->remove(resource);
312        }
313      else
314        PRINTF(4)("Resource %s not removed, because there are still %d References to it.\n", resource->name, resource->count);
315    }
316  else
317    PRINTF(4)("not deleting resource %s because DeleteLevel to high\n", resource->name);
318  return true;
319}
320
321
322/**
323   \brief unloads all alocated Memory of Resources with a pririty lower than prio
324   \param prio The priority to delete
325*/
326bool ResourceManager::unloadAllByPriority(ResourcePriority prio)
327{
328  tIterator<Resource>* iterator = resourceList->getIterator();
329  Resource* enumRes = iterator->nextElement();
330  while (enumRes)
331    {
332      if (enumRes->prio <= prio)
333        unload(enumRes, prio);
334      //enumRes = resourceList->nextElement();
335      enumRes = iterator->nextElement();
336    }
337  delete iterator;
338}
339
340/**
341   \brief Searches for a Resource by Name
342   \param fileName The name to look for
343   \returns a Pointer to the Resource if found, NULL otherwise.
344*/
345Resource* ResourceManager::locateResourceByName(const char* fileName)
346{
347  //  Resource* enumRes = resourceList->enumerate();
348  tIterator<Resource>* iterator = resourceList->getIterator();
349  Resource* enumRes = iterator->nextElement();
350  while (enumRes)
351    {
352      if (!strcmp(fileName, enumRes->name))
353        {
354          delete iterator;
355          return enumRes;
356        }
357      enumRes = iterator->nextElement();
358    }
359  delete iterator;
360  return NULL;
361}
362
363/**
364   \brief Searches for a Resource by Pointer
365   \param pointer the Pointer to search for
366   \returns a Pointer to the Resource if found, NULL otherwise.
367*/
368Resource* ResourceManager::locateResourceByPointer(const void* pointer)
369{
370  //  Resource* enumRes = resourceList->enumerate();
371  tIterator<Resource>* iterator = resourceList->getIterator();
372  Resource* enumRes = iterator->nextElement();
373  while (enumRes)
374    {
375      if (pointer == enumRes->pointer)
376        {
377          delete iterator;
378          return enumRes;
379        }
380      enumRes = iterator->nextElement();
381    }
382  delete iterator;
383  return NULL;
384}
385
386/**
387   \brief Checks if it is a Directory
388   \param directoryName the Directory to check for
389   \returns true if it is a directory/symlink false otherwise
390*/
391bool ResourceManager::isDir(const char* directoryName)
392{
393  struct stat status;
394  stat(directoryName, &status);
395  if (status.st_mode & (S_IFDIR | S_IFLNK))
396    return true;
397  else
398    return false;
399}
400
401/**
402   \brief Checks if the file is either a Regular file or a Symlink
403   \param fileName the File to check for
404   \returns true if it is a regular file/symlink, false otherwise
405*/
406bool ResourceManager::isFile(const char* fileName)
407{
408  struct stat status;
409  stat(fileName, &status);
410  if (status.st_mode & (S_IFREG | S_IFLNK))
411    return true;
412  else
413    return false;
414}
Note: See TracBrowser for help on using the repository browser.