Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: debug-information for ResourceManager

File size: 12.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: 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              PRINTF(4)("Image %s resides to %s\n", fileName, fullName);
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                    {
233                      PRINTF(4)("Image %s resides to %s\n", fileName, imgName);
234                      tmpResource->pointer = new Texture(imgName);
235                      delete []imgName;
236                      break;
237                    }
238                  delete []imgName;
239                  tmpDir = iterator->nextElement();
240                }
241              delete iterator;
242            }
243          if(!tmpResource)
244             PRINTF(2)("!!Image %s not Found!!\n", fileName);
245          break;
246        default:
247          tmpResource->pointer = NULL;
248          PRINTF(1)("No type found for %s.\n   !!This should not happen unless the Type is not supported yet.!!\n", tmpResource->name);
249          break;
250        }
251      this->resourceList->add(tmpResource);
252      delete []fullName;
253    }
254  else
255    {
256      PRINTF(4)("not loading cached resource %s\n", tmpResource->name);
257      tmpResource->count++;
258      if(tmpResource->prio < prio)
259        tmpResource->prio = prio;
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        unload(enumRes, prio);
333      //enumRes = resourceList->nextElement();
334      enumRes = iterator->nextElement();
335    }
336  delete iterator;
337}
338
339/**
340   \brief Searches for a Resource by Name
341   \param fileName The name to look for
342   \returns a Pointer to the Resource if found, NULL otherwise.
343*/
344Resource* ResourceManager::locateResourceByName(const char* fileName)
345{
346  //  Resource* enumRes = resourceList->enumerate();
347  tIterator<Resource>* iterator = resourceList->getIterator();
348  Resource* enumRes = iterator->nextElement();
349  while (enumRes)
350    {
351      if (!strcmp(fileName, enumRes->name))
352        {
353          delete iterator;
354          return enumRes;
355        }
356      enumRes = iterator->nextElement();
357    }
358  delete iterator;
359  return NULL;
360}
361
362/**
363   \brief Searches for a Resource by Pointer
364   \param pointer the Pointer to search for
365   \returns a Pointer to the Resource if found, NULL otherwise.
366*/
367Resource* ResourceManager::locateResourceByPointer(const void* pointer)
368{
369  //  Resource* enumRes = resourceList->enumerate();
370  tIterator<Resource>* iterator = resourceList->getIterator();
371  Resource* enumRes = iterator->nextElement();
372  while (enumRes)
373    {
374      if (pointer == enumRes->pointer)
375        {
376          delete iterator;
377          return enumRes;
378        }
379      enumRes = iterator->nextElement();
380    }
381  delete iterator;
382  return NULL;
383}
384
385/**
386   \brief Checks if it is a Directory
387   \param directoryName the Directory to check for
388   \returns true if it is a directory/symlink false otherwise
389*/
390bool ResourceManager::isDir(const char* directoryName)
391{
392  struct stat status;
393  stat(directoryName, &status);
394  if (status.st_mode & (S_IFDIR | S_IFLNK))
395    return true;
396  else
397    return false;
398}
399
400/**
401   \brief Checks if the file is either a Regular file or a Symlink
402   \param fileName the File to check for
403   \returns true if it is a regular file/symlink, false otherwise
404*/
405bool ResourceManager::isFile(const char* fileName)
406{
407  struct stat status;
408  stat(fileName, &status);
409  if (status.st_mode & (S_IFREG | S_IFLNK))
410    return true;
411  else
412    return false;
413}
414
415/**
416   \brief outputs debug information about the ResourceManager
417*/
418void ResourceManager::debug(void)
419{
420  PRINT(0)("=RM===================================\n");
421  PRINT(0)("= RESOURCE-MANAGER DEBUG INFORMATION =\n");
422  PRINT(0)("======================================\n");
423  // if it is not initialized
424  PRINT(0)(" Reference is: %p\n", ResourceManager::singletonRef);
425  PRINT(0)(" Data-Directory is: %s\n", this->dataDir);
426  PRINT(0)(" List of Image-Directories: ");
427  tIterator<char>* tmpIt = imageDirs->getIterator();
428  char* tmpDir = tmpIt->nextElement();
429  while(tmpDir)
430    {
431      PRINT(0)("%s ",tmpDir);
432      tmpDir = tmpIt->nextElement();
433    }
434  delete tmpIt;
435  PRINT(0)("\n");
436
437  PRINT(0)("List of all stored Resources:\n");
438  tIterator<Resource>* iterator = resourceList->getIterator();
439  Resource* enumRes = iterator->nextElement();
440  while (enumRes)
441    {
442      PRINT(0)("-----------------------------------------\n");
443      PRINT(0)("Name: %s; References: %d; Type:", enumRes->name, enumRes->count);
444      switch (enumRes->type)
445        {
446        case OBJ:
447          PRINT(0)("ObjectModel\n");
448          break;
449        case PRIM:
450          PRINT(0)("PrimitiveModel\n");
451          break;
452        case IMAGE:
453          PRINT(0)("ImageFile (Texture)\n");
454          break;
455        default:
456          PRINT(0)("SoundFile\n");
457          break;
458        }
459      PRINT(0)("gets deleted at ");
460      switch(enumRes->prio)
461        {
462        default:
463        case RP_NO:
464          PRINT(0)("first posibility (0)\n");
465          break;
466        case RP_LEVEL:
467          PRINT(0)("the end of the Level (1)\n");
468          break;
469        case RP_CAMPAIGN:
470          PRINT(0)("the end of the campaign (2)\n");
471          break;
472        case RP_GAME:
473          PRINT(0)("when leaving the game (3)\n");
474          break;
475        }
476      enumRes = iterator->nextElement();
477    }
478  delete iterator;
479
480
481
482  PRINT(0)("==================================RM==\n");
483}
Note: See TracBrowser for help on using the repository browser.