Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 3771 was 3769, checked in by bensch, 20 years ago

orxonox/branches/textEngine: compiling again, many movements… still working

File size: 13.2 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            default:
312              PRINTF(1)("NOT YET IMPLEMENTED !!FIX FIX!!\n");
313              return false;
314              break;
315            }
316          // deleting the List Entry:
317          PRINTF(4)("Resource %s safely removed.\n", resource->name);
318          delete []resource->name;
319          this->resourceList->remove(resource);
320        }
321      else
322        PRINTF(4)("Resource %s not removed, because there are still %d References to it.\n", resource->name, resource->count);
323    }
324  else
325    PRINTF(4)("not deleting resource %s because DeleteLevel to high\n", resource->name);
326  return true;
327}
328
329
330/**
331   \brief unloads all alocated Memory of Resources with a pririty lower than prio
332   \param prio The priority to delete
333*/
334bool ResourceManager::unloadAllByPriority(ResourcePriority prio)
335{
336  tIterator<Resource>* iterator = resourceList->getIterator();
337  Resource* enumRes = iterator->nextElement();
338  while (enumRes)
339    {
340      if (enumRes->prio <= prio)
341        if (enumRes->count == 0)
342          unload(enumRes, prio);
343        else
344          PRINTF(2)("unable to unload %s because there are still %d references to it\n",
345                   enumRes->name, enumRes->count);
346      //enumRes = resourceList->nextElement();
347      enumRes = iterator->nextElement();
348    }
349  delete iterator;
350}
351
352/**
353   \brief Searches for a Resource by Name
354   \param fileName The name to look for
355   \returns a Pointer to the Resource if found, NULL otherwise.
356*/
357Resource* ResourceManager::locateResourceByName(const char* fileName)
358{
359  //  Resource* enumRes = resourceList->enumerate();
360  tIterator<Resource>* iterator = resourceList->getIterator();
361  Resource* enumRes = iterator->nextElement();
362  while (enumRes)
363    {
364      if (!strcmp(fileName, enumRes->name))
365        {
366          delete iterator;
367          return enumRes;
368        }
369      enumRes = iterator->nextElement();
370    }
371  delete iterator;
372  return NULL;
373}
374
375/**
376   \brief Searches for a Resource by Pointer
377   \param pointer the Pointer to search for
378   \returns a Pointer to the Resource if found, NULL otherwise.
379*/
380Resource* ResourceManager::locateResourceByPointer(const void* pointer)
381{
382  //  Resource* enumRes = resourceList->enumerate();
383  tIterator<Resource>* iterator = resourceList->getIterator();
384  Resource* enumRes = iterator->nextElement();
385  while (enumRes)
386    {
387      if (pointer == enumRes->pointer)
388        {
389          delete iterator;
390          return enumRes;
391        }
392      enumRes = iterator->nextElement();
393    }
394  delete iterator;
395  return NULL;
396}
397
398/**
399   \brief Checks if it is a Directory
400   \param directoryName the Directory to check for
401   \returns true if it is a directory/symlink false otherwise
402*/
403bool ResourceManager::isDir(const char* directoryName)
404{
405  struct stat status;
406  stat(directoryName, &status);
407  if (status.st_mode & (S_IFDIR
408#ifndef __WIN32__
409                        | S_IFLNK
410#endif
411                        ))
412    return true;
413  else
414    return false;
415}
416
417/**
418   \brief Checks if the file is either a Regular file or a Symlink
419   \param fileName the File to check for
420   \returns true if it is a regular file/symlink, false otherwise
421*/
422bool ResourceManager::isFile(const char* fileName)
423{
424  struct stat status;
425  stat(fileName, &status);
426  if (status.st_mode & (S_IFREG
427#ifndef __WIN32__
428                        | S_IFLNK
429#endif
430                        ))
431    return true;
432  else
433    return false;
434}
435
436/**
437   \brief outputs debug information about the ResourceManager
438*/
439void ResourceManager::debug(void)
440{
441  PRINT(0)("=RM===================================\n");
442  PRINT(0)("= RESOURCE-MANAGER DEBUG INFORMATION =\n");
443  PRINT(0)("======================================\n");
444  // if it is not initialized
445  PRINT(0)(" Reference is: %p\n", ResourceManager::singletonRef);
446  PRINT(0)(" Data-Directory is: %s\n", this->dataDir);
447  PRINT(0)(" List of Image-Directories: ");
448  tIterator<char>* tmpIt = imageDirs->getIterator();
449  char* tmpDir = tmpIt->nextElement();
450  while(tmpDir)
451    {
452      PRINT(0)("%s ",tmpDir);
453      tmpDir = tmpIt->nextElement();
454    }
455  delete tmpIt;
456  PRINT(0)("\n");
457
458  PRINT(0)("List of all stored Resources:\n");
459  tIterator<Resource>* iterator = resourceList->getIterator();
460  Resource* enumRes = iterator->nextElement();
461  while (enumRes)
462    {
463      PRINT(0)("-----------------------------------------\n");
464      PRINT(0)("Name: %s; References: %d; Type:", enumRes->name, enumRes->count);
465      switch (enumRes->type)
466        {
467        case OBJ:
468          PRINT(0)("ObjectModel\n");
469          break;
470        case PRIM:
471          PRINT(0)("PrimitiveModel\n");
472          break;
473        case IMAGE:
474          PRINT(0)("ImageFile (Texture)\n");
475          break;
476        default:
477          PRINT(0)("SoundFile\n");
478          break;
479        }
480      PRINT(0)("gets deleted at ");
481      switch(enumRes->prio)
482        {
483        default:
484        case RP_NO:
485          PRINT(0)("first posibility (0)\n");
486          break;
487        case RP_LEVEL:
488          PRINT(0)("the end of the Level (1)\n");
489          break;
490        case RP_CAMPAIGN:
491          PRINT(0)("the end of the campaign (2)\n");
492          break;
493        case RP_GAME:
494          PRINT(0)("when leaving the game (3)\n");
495          break;
496        }
497      enumRes = iterator->nextElement();
498    }
499  delete iterator;
500
501
502
503  PRINT(0)("==================================RM==\n");
504}
Note: See TracBrowser for help on using the repository browser.