Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: caching better implemented, now there should be no more seg-fault
@patrick: new List-iterator did not work → got segfault with it

File size: 10.6 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  Resource* enumRes = resourceList->enumerate();
327  while (enumRes)
328    {
329      if (enumRes->prio <= prio)
330        unload(enumRes, prio);
331      enumRes = resourceList->nextElement();
332    }
333}
334
335/**
336   \brief Searches for a Resource by Name
337   \param fileName The name to look for
338   \returns a Pointer to the Resource if found, NULL otherwise.
339*/
340Resource* ResourceManager::locateResourceByName(const char* fileName)
341{
342  Resource* enumRes = resourceList->enumerate();
343  while (enumRes)
344    {
345      if (!strcmp(fileName, enumRes->name))
346        return enumRes;
347      enumRes = resourceList->nextElement();
348    }
349  return NULL;
350}
351
352/**
353   \brief Searches for a Resource by Pointer
354   \param pointer the Pointer to search for
355   \returns a Pointer to the Resource if found, NULL otherwise.
356*/
357Resource* ResourceManager::locateResourceByPointer(const void* pointer)
358{
359  Resource* enumRes = resourceList->enumerate();
360  while (enumRes)
361    {
362      if (pointer == enumRes->pointer)
363        return enumRes;
364      enumRes = resourceList->nextElement();
365    }
366  return NULL;
367}
368
369/**
370   \brief Checks if it is a Directory
371   \param directoryName the Directory to check for
372   \returns true if it is a directory/symlink false otherwise
373*/
374bool ResourceManager::isDir(const char* directoryName)
375{
376  struct stat status;
377  stat(directoryName, &status);
378  if (status.st_mode & (S_IFDIR | S_IFLNK))
379    return true;
380  else
381    return false;
382}
383
384/**
385   \brief Checks if the file is either a Regular file or a Symlink
386   \param fileName the File to check for
387   \returns true if it is a regular file/symlink, false otherwise
388*/
389bool ResourceManager::isFile(const char* fileName)
390{
391  struct stat status;
392  stat(fileName, &status);
393  if (status.st_mode & (S_IFREG | S_IFLNK))
394    return true;
395  else
396    return false;
397}
Note: See TracBrowser for help on using the repository browser.