Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: changed all old enumerations to iterations in ResourceManager. Bensch: sorry for interference, since i didn't change anything realy its no big deal.

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