Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/branches/textEngine: unloading works

File size: 13.3 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#include "text_engine.h"
25
26#include "list.h"
27
28// File Handling Includes
29#include <sys/types.h>
30#include <sys/stat.h>
31#include <unistd.h>
32
33using namespace std;
34
35/**
36   \brief standard constructor
37*/
38ResourceManager::ResourceManager () 
39{
40   this->setClassName ("ResourceManager");
41   this->dataDir = "./";
42   this->imageDirs = new tList<char>();
43   this->resourceList = new tList<Resource>();
44}
45
46/**
47   \returns the Instance to this ResourceManager
48*/
49ResourceManager* ResourceManager::getInstance(void)
50{
51  if (!ResourceManager::singletonRef)
52    ResourceManager::singletonRef = new ResourceManager();
53  return ResourceManager::singletonRef;
54}
55
56//! Singleton Reference to the ResourceManager
57ResourceManager* ResourceManager::singletonRef = NULL;
58
59/**
60   \brief standard destructor
61*/
62ResourceManager::~ResourceManager (void) 
63{
64  // deleting the Resources-List
65  this->unloadAllByPriority(RP_GAME);
66  delete this->resourceList;
67  // deleting the Directorie Lists
68  tIterator<char>* tmpIt = imageDirs->getIterator();
69  char* tmpDir = tmpIt->nextElement();
70  while(tmpDir)
71    {
72      delete []tmpDir;
73      tmpDir = tmpIt->nextElement();
74    }
75  delete tmpIt;
76
77  delete this->imageDirs;
78
79  ResourceManager::singletonRef = NULL;
80}
81
82/**
83   \brief sets the data main directory
84   \param dataDir the DataDirectory.
85*/
86bool ResourceManager::setDataDir(char* dataDir)
87{
88  if (isDir(dataDir))
89    {
90      this->dataDir = new char[strlen(dataDir)+1];
91      strcpy(this->dataDir, dataDir);
92    }
93  else
94    {
95      PRINTF(1)("%s is not a Directory, and can not be the Data Directory\n", dataDir);
96    }
97}
98
99/**
100   \brief adds a new Path for Images
101   \param imageDir The path to insert
102   \returns true, if the Path was well and injected (or already existent within the list)
103   false otherwise
104*/
105bool ResourceManager::addImageDir(char* imageDir)
106{
107  // check if the param is a Directory
108  if (isDir(imageDir))
109    {
110      // check if the Directory has been added before
111      tIterator<char>* tmpImageDirs = imageDirs->getIterator();
112      char* tmpDir = tmpImageDirs->nextElement();
113      while(tmpDir)
114        {
115          if (!strcmp(tmpDir, imageDir))
116            {
117              PRINTF(4)("Path %s already loaded\n", imageDir);
118              delete tmpImageDirs;
119              return true;
120            }
121          tmpDir = tmpImageDirs->nextElement();
122        }
123      delete tmpImageDirs;
124
125      // adding the directory to the List
126      tmpDir  = new char[strlen(imageDir)+1];
127      strcpy(tmpDir, imageDir);
128      this->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 if (!strncmp(fileName+(strlen(fileName)-4), ".ttf", 4))
162    tmpType = TTF;
163  else 
164    tmpType = IMAGE;
165
166  return this->load(fileName, tmpType, prio);
167}
168
169/**
170   \brief loads resources
171   \param fileName The fileName of the resource to load
172   \param type The Type of Resource to load (\see ResourceType)
173   \param prio The ResourcePriority of this resource (will only be increased)
174   \returns a pointer to a desired Resource.
175*/
176void* ResourceManager::load(const char* fileName, ResourceType type, ResourcePriority prio)
177{
178  // searching if the resource was loaded before.
179  Resource* tmpResource = this->locateResourceByName(fileName);
180  if (tmpResource) // if the resource was not loaded before.
181    {
182      PRINTF(4)("not loading cached resource %s\n", tmpResource->name);
183      tmpResource->count++;
184      if(tmpResource->prio < prio)
185        tmpResource->prio = prio;
186    }
187  else
188    {
189      char* tmpDir;
190      // Setting up the new Resource
191      tmpResource = new Resource;
192      tmpResource->count = 1;
193      tmpResource->type = type;
194      tmpResource->prio = prio;
195      tmpResource->name = new char[strlen(fileName)+1];
196      strcpy(tmpResource->name, fileName);
197
198      // creating the full name. (directoryName + FileName)
199      char* fullName = new char[strlen(dataDir)+strlen(fileName)+1];
200      sprintf(fullName, "%s%s", this->dataDir, fileName);
201     
202      // Checking for the type of resource \see ResourceType
203      switch(type)
204        {
205        case OBJ:
206          if(isFile(fullName))
207            tmpResource->pointer = new OBJModel(fullName);
208          else
209            {
210              PRINTF(2)("Sorry, %s does not exist. Loading a cube-Model instead\n", fullName);
211              tmpResource->pointer = ResourceManager::load("cube", PRIM);
212            }
213          break;
214        case PRIM:
215          if (!strcmp(tmpResource->name, "cube"))
216            tmpResource->pointer = new PrimitiveModel(CUBE);
217          else if (!strcmp(tmpResource->name, "sphere"))
218            tmpResource->pointer = new PrimitiveModel(SPHERE);
219          else if (!strcmp(tmpResource->name, "plane"))
220            tmpResource->pointer = new PrimitiveModel(PLANE);
221          else if (!strcmp(tmpResource->name, "cylinder"))
222            tmpResource->pointer = new PrimitiveModel(CYLINDER);
223          else if (!strcmp(tmpResource->name, "cone"))
224            tmpResource->pointer = new PrimitiveModel(CONE);
225          break;
226        case TTF:
227          if(isFile(fullName))
228            tmpResource->pointer = new Font(fullName);
229          else
230            PRINTF(2)("Sorry, %s does not exist. Not loading Font\n", fullName);
231          break;
232        case IMAGE:
233          if(isFile(fullName))
234            {
235              PRINTF(4)("Image %s resides to %s\n", fileName, fullName);
236              tmpResource->pointer = new Texture(fullName);
237            }
238          else
239            {
240              tIterator<char>* iterator = imageDirs->getIterator();
241              tmpDir = iterator->nextElement();
242              //tmpDir = imageDirs->enumerate();
243              while(tmpDir)
244                {
245                  char* imgName = new char[strlen(tmpDir)+strlen(fileName)+1];
246                  sprintf(imgName, "%s%s", tmpDir, fileName);
247                  if(isFile(imgName))
248                    {
249                      PRINTF(4)("Image %s resides to %s\n", fileName, imgName);
250                      tmpResource->pointer = new Texture(imgName);
251                      delete []imgName;
252                      break;
253                    }
254                  delete []imgName;
255                  tmpDir = iterator->nextElement();
256                }
257              delete iterator;
258            }
259          if(!tmpResource)
260             PRINTF(2)("!!Image %s not Found!!\n", fileName);
261          break;
262        default:
263          tmpResource->pointer = NULL;
264          PRINTF(1)("No type found for %s.\n   !!This should not happen unless the Type is not supported yet.!!\n", tmpResource->name);
265          break;
266        }
267      this->resourceList->add(tmpResource);
268      delete []fullName;
269    }
270
271  return tmpResource->pointer;
272}
273
274/**
275   \brief unloads a Resource
276   \param pointer The pointer to free
277   \returns true if successful (pointer found, and deleted), false otherwise
278   
279*/
280bool ResourceManager::unload(void* pointer, ResourcePriority prio)
281{
282  // if pointer is existent. and only one resource of this type exists.
283  Resource* tmpResource = this->locateResourceByPointer(pointer);
284  if (!tmpResource)
285    {
286      PRINTF(2)("Resource not Found %p\n", pointer);
287      return false;
288    }
289  else
290    unload(tmpResource, prio);
291}
292
293bool ResourceManager::unload(Resource* resource, ResourcePriority prio)
294{
295  if (resource->count > 0)
296    resource->count--;
297  if (resource->prio <= prio)
298    {
299      if (resource->count <= 0)
300        {
301          // deleting the Resource
302          switch(resource->type)
303            {
304            case OBJ:
305            case PRIM:
306              delete (Model*)resource->pointer;
307              break;
308            case IMAGE:
309              delete (Texture*)resource->pointer;
310              break;
311            case TTF:
312              delete (Font*)resource->pointer;
313              break;
314            default:
315              PRINTF(1)("NOT YET IMPLEMENTED !!FIX FIX!!\n");
316              return false;
317              break;
318            }
319          // deleting the List Entry:
320          PRINTF(4)("Resource %s safely removed.\n", resource->name);
321          delete []resource->name;
322          this->resourceList->remove(resource);
323        }
324      else
325        PRINTF(4)("Resource %s not removed, because there are still %d References to it.\n", resource->name, resource->count);
326    }
327  else
328    PRINTF(4)("not deleting resource %s because DeleteLevel to high\n", resource->name);
329  return true;
330}
331
332
333/**
334   \brief unloads all alocated Memory of Resources with a pririty lower than prio
335   \param prio The priority to delete
336*/
337bool ResourceManager::unloadAllByPriority(ResourcePriority prio)
338{
339  tIterator<Resource>* iterator = resourceList->getIterator();
340  Resource* enumRes = iterator->nextElement();
341  while (enumRes)
342    {
343      if (enumRes->prio <= prio)
344        if (enumRes->count == 0)
345          unload(enumRes, prio);
346        else
347          PRINTF(2)("unable to unload %s because there are still %d references to it\n",
348                   enumRes->name, enumRes->count);
349      //enumRes = resourceList->nextElement();
350      enumRes = iterator->nextElement();
351    }
352  delete iterator;
353}
354
355/**
356   \brief Searches for a Resource by Name
357   \param fileName The name to look for
358   \returns a Pointer to the Resource if found, NULL otherwise.
359*/
360Resource* ResourceManager::locateResourceByName(const char* fileName)
361{
362  //  Resource* enumRes = resourceList->enumerate();
363  tIterator<Resource>* iterator = resourceList->getIterator();
364  Resource* enumRes = iterator->nextElement();
365  while (enumRes)
366    {
367      if (!strcmp(fileName, enumRes->name))
368        {
369          delete iterator;
370          return enumRes;
371        }
372      enumRes = iterator->nextElement();
373    }
374  delete iterator;
375  return NULL;
376}
377
378/**
379   \brief Searches for a Resource by Pointer
380   \param pointer the Pointer to search for
381   \returns a Pointer to the Resource if found, NULL otherwise.
382*/
383Resource* ResourceManager::locateResourceByPointer(const void* pointer)
384{
385  //  Resource* enumRes = resourceList->enumerate();
386  tIterator<Resource>* iterator = resourceList->getIterator();
387  Resource* enumRes = iterator->nextElement();
388  while (enumRes)
389    {
390      if (pointer == enumRes->pointer)
391        {
392          delete iterator;
393          return enumRes;
394        }
395      enumRes = iterator->nextElement();
396    }
397  delete iterator;
398  return NULL;
399}
400
401/**
402   \brief Checks if it is a Directory
403   \param directoryName the Directory to check for
404   \returns true if it is a directory/symlink false otherwise
405*/
406bool ResourceManager::isDir(const char* directoryName)
407{
408  struct stat status;
409  stat(directoryName, &status);
410  if (status.st_mode & (S_IFDIR
411#ifndef __WIN32__
412                        | S_IFLNK
413#endif
414                        ))
415    return true;
416  else
417    return false;
418}
419
420/**
421   \brief Checks if the file is either a Regular file or a Symlink
422   \param fileName the File to check for
423   \returns true if it is a regular file/symlink, false otherwise
424*/
425bool ResourceManager::isFile(const char* fileName)
426{
427  struct stat status;
428  stat(fileName, &status);
429  if (status.st_mode & (S_IFREG
430#ifndef __WIN32__
431                        | S_IFLNK
432#endif
433                        ))
434    return true;
435  else
436    return false;
437}
438
439/**
440   \brief outputs debug information about the ResourceManager
441*/
442void ResourceManager::debug(void)
443{
444  PRINT(0)("=RM===================================\n");
445  PRINT(0)("= RESOURCE-MANAGER DEBUG INFORMATION =\n");
446  PRINT(0)("======================================\n");
447  // if it is not initialized
448  PRINT(0)(" Reference is: %p\n", ResourceManager::singletonRef);
449  PRINT(0)(" Data-Directory is: %s\n", this->dataDir);
450  PRINT(0)(" List of Image-Directories: ");
451  tIterator<char>* tmpIt = imageDirs->getIterator();
452  char* tmpDir = tmpIt->nextElement();
453  while(tmpDir)
454    {
455      PRINT(0)("%s ",tmpDir);
456      tmpDir = tmpIt->nextElement();
457    }
458  delete tmpIt;
459  PRINT(0)("\n");
460
461  PRINT(0)("List of all stored Resources:\n");
462  tIterator<Resource>* iterator = resourceList->getIterator();
463  Resource* enumRes = iterator->nextElement();
464  while (enumRes)
465    {
466      PRINT(0)("-----------------------------------------\n");
467      PRINT(0)("Name: %s; References: %d; Type:", enumRes->name, enumRes->count);
468      switch (enumRes->type)
469        {
470        case OBJ:
471          PRINT(0)("ObjectModel\n");
472          break;
473        case PRIM:
474          PRINT(0)("PrimitiveModel\n");
475          break;
476        case IMAGE:
477          PRINT(0)("ImageFile (Texture)\n");
478          break;
479        default:
480          PRINT(0)("SoundFile\n");
481          break;
482        }
483      PRINT(0)("gets deleted at ");
484      switch(enumRes->prio)
485        {
486        default:
487        case RP_NO:
488          PRINT(0)("first posibility (0)\n");
489          break;
490        case RP_LEVEL:
491          PRINT(0)("the end of the Level (1)\n");
492          break;
493        case RP_CAMPAIGN:
494          PRINT(0)("the end of the campaign (2)\n");
495          break;
496        case RP_GAME:
497          PRINT(0)("when leaving the game (3)\n");
498          break;
499        }
500      enumRes = iterator->nextElement();
501    }
502  delete iterator;
503
504
505
506  PRINT(0)("==================================RM==\n");
507}
Note: See TracBrowser for help on using the repository browser.