Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 3749 was 3703, checked in by bensch, 20 years ago

orxonox/branches/textEngine: orxonox compiles under Windows again
@patrick: i had to disable benchMark in orxonox.cc (with #ifndef WIN32) see for yourself

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