Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 3666 was 3666, checked in by patrick, 19 years ago

orxonox/trunk: still got segfault because of deprecated list enumeration method in resourcemanager. changed to iterator, now there are no segfaults anymore.

File size: 10.7 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: ...
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   dataDir = NULL;
41   imageDirs = new tList<char>();
42   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//! The List of Resources, that has already been loaded.
58tList<Resource>* ResourceManager::resourceList = NULL;
59//! The Data Directory, where all relevant Data is stored.
60char* ResourceManager::dataDir = NULL;
61//! A list of directories in which images are stored.
62tList<char>* ResourceManager::imageDirs = NULL;
63
64/**
65   \brief standard destructor
66*/
67ResourceManager::~ResourceManager (void) 
68{
69  // deleting the Resources-List
70  unloadAllByPriority(RP_GAME);
71  delete resourceList;
72  resourceList = NULL;
73  // deleting the Directorie Lists
74  char* tmpDir = imageDirs->enumerate();
75  while(tmpDir)
76    {
77      delete []tmpDir;
78      tmpDir = imageDirs->nextElement();
79    }
80
81  delete imageDirs;
82  imageDirs = NULL;
83  ResourceManager::singletonRef = NULL;
84}
85
86/**
87   \brief sets the data main directory
88   \param dataDir the DataDirectory.
89*/
90bool ResourceManager::setDataDir(char* dataDir)
91{
92  if (isDir(dataDir))
93    {
94      ResourceManager::dataDir = new char[strlen(dataDir)+1];
95      strcpy(ResourceManager::dataDir, dataDir);
96    }
97  else
98    {
99      PRINTF(1)("%s is not a Directory, and can not be the Data Directory\n", dataDir);
100    }
101}
102
103/**
104   \brief adds a new Path for Images
105   \param imageDir The path to insert
106   \returns true, if the Path was well and injected (or already existent within the list)
107   false otherwise
108*/
109bool ResourceManager::addImageDir(char* imageDir)
110{
111  // check if the param is a Directory
112  if (isDir(imageDir))
113    {
114      // check if the Directory has been added before
115      char* tmpDir = imageDirs->enumerate();
116      while(tmpDir)
117        {
118          if (!strcmp(tmpDir, imageDir))
119            {
120              PRINTF(4)("Path %s already loaded\n", imageDir);
121              return true;
122            }
123          tmpDir = imageDirs->nextElement();
124        }
125      // adding the directory to the List
126      tmpDir  = new char[strlen(imageDir)+1];
127      strcpy(tmpDir, imageDir);
128      imageDirs->add(tmpDir);
129      return true;
130    }
131  else
132    {
133      PRINTF(1)("%s is not a Directory, and can not be added to the Paths of Images\n", dataDir);
134      return false;
135    }
136}
137
138/**
139   \brief loads resources
140   \param fileName The fileName of the resource to load
141   \param prio The ResourcePriority of this resource (will only be increased)
142   \returns a pointer to a desired Resource.
143*/
144void* ResourceManager::load(const char* fileName, ResourcePriority prio)
145{
146  ResourceType tmpType;
147  if (!strncmp(fileName+(strlen(fileName)-4), ".obj", 4))
148    tmpType = OBJ;
149  else if (!strncmp(fileName+(strlen(fileName)-4), ".wav", 4))
150    tmpType = WAV;
151  else if (!strncmp(fileName+(strlen(fileName)-4), ".mp3", 4))
152    tmpType = MP3;
153  else if (!strncmp(fileName+(strlen(fileName)-4), ".ogg", 4))
154    tmpType = OGG;
155  else if (!strcmp(fileName, "cube") ||
156           !strcmp(fileName, "sphere") ||
157           !strcmp(fileName, "plane") ||
158           !strcmp(fileName, "cylinder") ||
159           !strcmp(fileName, "cone"))
160    tmpType = PRIM;
161  else 
162    tmpType = IMAGE;
163
164  return ResourceManager::load(fileName, tmpType, prio);
165}
166
167/**
168   \brief loads resources
169   \param fileName The fileName of the resource to load
170   \param type The Type of Resource to load (\see ResourceType)
171   \param prio The ResourcePriority of this resource (will only be increased)
172   \returns a pointer to a desired Resource.
173*/
174void* ResourceManager::load(const char* fileName, ResourceType type, ResourcePriority prio)
175{
176  // searching if the resource was loaded before.
177  Resource* tmpResource = ResourceManager::locateResourceByName(fileName);
178  if (!tmpResource) // if the resource was not loaded before.
179    {
180      char* tmpDir;
181      // Setting up the new Resource
182      tmpResource = new Resource;
183      tmpResource->count = 1;
184      tmpResource->type = type;
185      tmpResource->prio = prio;
186      tmpResource->name = new char[strlen(fileName)+1];
187      strcpy(tmpResource->name, fileName);
188
189      // creating the full name. (directoryName + FileName)
190      char* fullName = new char[strlen(dataDir)+strlen(fileName)+1];
191      sprintf(fullName, "%s%s", dataDir, fileName);
192     
193      // Checking for the type of resource \see ResourceType
194      switch(type)
195        {
196        case OBJ:
197          if(isFile(fullName))
198            tmpResource->pointer = new OBJModel(fullName);
199          else
200            {
201              PRINTF(2)("Sorry, %s does not exist. Loading a cube-Model instead\n", fullName);
202              tmpResource->pointer = ResourceManager::load("cube", PRIM);
203            }
204          break;
205        case PRIM:
206          if (!strcmp(tmpResource->name, "cube"))
207            tmpResource->pointer = new PrimitiveModel(CUBE);
208          else if (!strcmp(tmpResource->name, "sphere"))
209            tmpResource->pointer = new PrimitiveModel(SPHERE);
210          else if (!strcmp(tmpResource->name, "plane"))
211            tmpResource->pointer = new PrimitiveModel(PLANE);
212          else if (!strcmp(tmpResource->name, "cylinder"))
213            tmpResource->pointer = new PrimitiveModel(CYLINDER);
214          else if (!strcmp(tmpResource->name, "cone"))
215            tmpResource->pointer = new PrimitiveModel(CONE);
216          break;
217        case IMAGE:
218          if(isFile(fullName))
219            {
220              tmpResource->pointer = new Texture(fullName);
221            }
222          else
223            {
224              tmpDir = imageDirs->enumerate();
225              while(tmpDir)
226                {
227                  char* imgName = new char[strlen(tmpDir)+strlen(fileName)+1];
228                  sprintf(imgName, "%s%s", tmpDir, fileName);
229                  if(isFile(imgName))
230                    tmpResource->pointer = new Texture(imgName);
231                  delete []imgName;
232                  tmpDir = imageDirs->nextElement();
233                }
234            }
235          if(!tmpResource)
236             PRINTF(2)("!!Image %s not Found!!\n", fileName);
237          break;
238        default:
239          tmpResource->pointer = NULL;
240          PRINTF(1)("No type found for %s.\n   !!This should not happen unless the Type is not supported yet.!!\n", tmpResource->name);
241          break;
242        }
243     
244      // checking if the File really exists.
245      if(!isFile(fullName))
246        {
247          PRINTF(2)("Sorry, %s is not a regular file.\n", fullName);
248          tmpResource->pointer = NULL;
249        }
250      resourceList->add(tmpResource);
251      delete []fullName;
252    }
253  else
254    {
255      PRINTF(4)("not loading cached resource %s\n", tmpResource->name);
256      tmpResource->count++;
257      if(tmpResource->prio < prio)
258        tmpResource->prio = prio;
259    }
260
261  return tmpResource->pointer;
262}
263
264/**
265   \brief unloads a Resource
266   \param pointer The pointer to free
267   \returns true if successful (pointer found, and deleted), false otherwise
268   
269*/
270bool ResourceManager::unload(void* pointer, ResourcePriority prio)
271{
272  // if pointer is existent. and only one resource of this type exists.
273  Resource* tmpResource =ResourceManager::locateResourceByPointer(pointer);
274  if (!tmpResource)
275    {
276      PRINTF(2)("Resource not Found %p\n", pointer);
277      return false;
278    }
279  else
280    unload(tmpResource, prio);
281}
282
283bool ResourceManager::unload(Resource* resource, ResourcePriority prio)
284{
285  if (resource->count > 0)
286    resource->count--;
287  if (resource->prio <= prio)
288    {
289      if (resource->count <= 0)
290        {
291          // deleting the Resource
292          switch(resource->type)
293            {
294            case OBJ:
295            case PRIM:
296              delete (Model*)resource->pointer;
297              break;
298            case IMAGE:
299              delete (Texture*)resource->pointer;
300              break;
301            default:
302              PRINTF(1)("NOT YET IMPLEMENTED !!FIX FIX!!\n");
303              return false;
304              break;
305            }
306          // deleting the List Entry:
307          PRINTF(4)("Resource %s safely removed.\n", resource->name);
308          delete []resource->name;
309          resourceList->remove(resource);
310        }
311      else
312        PRINTF(4)("Resource %s not removed, because there are still %d References to it.\n", resource->name, resource->count);
313    }
314  else
315    PRINTF(4)("not deleting resource %s because DeleteLevel to high\n", resource->name);
316  return true;
317}
318
319
320/**
321   \brief unloads all alocated Memory of Resources with a pririty lower than prio
322   \param prio The priority to delete
323*/
324bool ResourceManager::unloadAllByPriority(ResourcePriority prio)
325{
326
327  tIterator<Resource>* iterator = resourceList->getIterator();
328  //Resource* enumRes = resourceList->enumerate();
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  while (enumRes)
349    {
350      if (!strcmp(fileName, enumRes->name))
351        return enumRes;
352      enumRes = resourceList->nextElement();
353    }
354  return NULL;
355}
356
357/**
358   \brief Searches for a Resource by Pointer
359   \param pointer the Pointer to search for
360   \returns a Pointer to the Resource if found, NULL otherwise.
361*/
362Resource* ResourceManager::locateResourceByPointer(const void* pointer)
363{
364  Resource* enumRes = resourceList->enumerate();
365  while (enumRes)
366    {
367      if (pointer == enumRes->pointer)
368        return enumRes;
369      enumRes = resourceList->nextElement();
370    }
371  return NULL;
372}
373
374/**
375   \brief Checks if it is a Directory
376   \param directoryName the Directory to check for
377   \returns true if it is a directory/symlink false otherwise
378*/
379bool ResourceManager::isDir(const char* directoryName)
380{
381  struct stat status;
382  stat(directoryName, &status);
383  if (status.st_mode & (S_IFDIR | S_IFLNK))
384    return true;
385  else
386    return false;
387}
388
389/**
390   \brief Checks if the file is either a Regular file or a Symlink
391   \param fileName the File to check for
392   \returns true if it is a regular file/symlink, false otherwise
393*/
394bool ResourceManager::isFile(const char* fileName)
395{
396  struct stat status;
397  stat(fileName, &status);
398  if (status.st_mode & (S_IFREG | S_IFLNK))
399    return true;
400  else
401    return false;
402}
Note: See TracBrowser for help on using the repository browser.