Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: now a check for a directory should return true also in Windows

File size: 16.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 = NULL;
42   this->setDataDir("./");
43   this->imageDirs = new tList<char>();
44   this->resourceList = new tList<Resource>();
45}
46
47/**
48   \returns the Instance to this ResourceManager
49*/
50ResourceManager* ResourceManager::getInstance(void)
51{
52  if (!ResourceManager::singletonRef)
53    ResourceManager::singletonRef = new ResourceManager();
54  return ResourceManager::singletonRef;
55}
56
57//! Singleton Reference to the ResourceManager
58ResourceManager* ResourceManager::singletonRef = NULL;
59
60/**
61   \brief standard destructor
62*/
63ResourceManager::~ResourceManager (void) 
64{
65  // deleting the Resources-List
66  this->unloadAllByPriority(RP_GAME);
67  delete this->resourceList;
68  // deleting the Directorie Lists
69  tIterator<char>* tmpIt = imageDirs->getIterator();
70  char* tmpDir = tmpIt->nextElement();
71  while(tmpDir)
72    {
73      delete []tmpDir;
74      tmpDir = tmpIt->nextElement();
75    }
76  delete tmpIt;
77
78  delete this->imageDirs;
79
80  ResourceManager::singletonRef = NULL;
81}
82
83/**
84   \brief sets the data main directory
85   \param dataDir the DataDirectory.
86*/
87bool ResourceManager::setDataDir(const char* dataDir)
88{
89  if (isDir(dataDir))
90    {
91      delete this->dataDir;
92      this->dataDir = new char[strlen(dataDir)+1];
93      strcpy(this->dataDir, dataDir);
94    }
95  else
96    {
97      PRINTF(1)("%s is not a Directory, and can not be the Data Directory, leaving as %s \n", dataDir, this->dataDir);
98    }
99}
100
101/**
102   \brief adds a new Path for Images
103   \param imageDir The path to insert
104   \returns true, if the Path was well and injected (or already existent within the list)
105   false otherwise
106*/
107bool ResourceManager::addImageDir(char* imageDir)
108{
109  // check if the param is a Directory
110  if (isDir(imageDir))
111    {
112      // check if the Directory has been added before
113      tIterator<char>* tmpImageDirs = imageDirs->getIterator();
114      char* tmpDir = tmpImageDirs->nextElement();
115      while(tmpDir)
116        {
117          if (!strcmp(tmpDir, imageDir))
118            {
119              PRINTF(4)("Path %s already loaded\n", imageDir);
120              delete tmpImageDirs;
121              return true;
122            }
123          tmpDir = tmpImageDirs->nextElement();
124        }
125      delete tmpImageDirs;
126
127      // adding the directory to the List
128      tmpDir  = new char[strlen(imageDir)+1];
129      strcpy(tmpDir, imageDir);
130      this->imageDirs->add(tmpDir);
131      return true;
132    }
133  else
134    {
135      PRINTF(1)("%s is not a Directory, and can not be added to the Paths of Images\n", dataDir);
136      return false;
137    }
138}
139
140/**
141   \brief loads resources
142   \param fileName The fileName of the resource to load
143   \param prio The ResourcePriority of this resource (will only be increased)
144   \returns a pointer to a desired Resource.
145*/
146void* ResourceManager::load(const char* fileName, ResourcePriority prio, void* param1, void* param2, void* param3)
147{
148  ResourceType tmpType;
149  if (!strncmp(fileName+(strlen(fileName)-4), ".obj", 4))
150    tmpType = OBJ;
151  else if (!strncmp(fileName+(strlen(fileName)-4), ".wav", 4))
152    tmpType = WAV;
153  else if (!strncmp(fileName+(strlen(fileName)-4), ".mp3", 4))
154    tmpType = MP3;
155  else if (!strncmp(fileName+(strlen(fileName)-4), ".ogg", 4))
156    tmpType = OGG;
157  else if (!strcmp(fileName, "cube") ||
158           !strcmp(fileName, "sphere") ||
159           !strcmp(fileName, "plane") ||
160           !strcmp(fileName, "cylinder") ||
161           !strcmp(fileName, "cone"))
162    tmpType = PRIM;
163  else if (!strncmp(fileName+(strlen(fileName)-4), ".ttf", 4))
164    tmpType = TTF;
165  else 
166    tmpType = IMAGE;
167
168  return this->load(fileName, tmpType, prio, param1, param2, param3);
169}
170
171/**
172   \brief loads resources
173   \param fileName The fileName of the resource to load
174   \param type The Type of Resource to load (\see ResourceType)
175   \param prio The ResourcePriority of this resource (will only be increased)
176   \returns a pointer to a desired Resource.
177*/
178void* ResourceManager::load(const char* fileName, ResourceType type, ResourcePriority prio, void* param1, void* param2, void* param3)
179{
180  // searching if the resource was loaded before.
181  Resource* tmpResource = this->locateResourceByInfo(fileName, type, param1, param2,param3);
182  if (tmpResource) // if the resource was not loaded before.
183    {
184      PRINTF(4)("not loading cached resource %s\n", tmpResource->name);
185      tmpResource->count++;
186      if(tmpResource->prio < prio)
187        tmpResource->prio = prio;
188    }
189  else
190    {
191      char* tmpDir;
192      // Setting up the new Resource
193      tmpResource = new Resource;
194      tmpResource->count = 1;
195      tmpResource->type = type;
196      tmpResource->prio = prio;
197      tmpResource->name = new char[strlen(fileName)+1];
198      strcpy(tmpResource->name, fileName);
199
200      // creating the full name. (directoryName + FileName)
201      char* fullName = new char[strlen(dataDir)+strlen(fileName)+1];
202      sprintf(fullName, "%s%s", this->dataDir, fileName);
203     
204      // Checking for the type of resource \see ResourceType
205      switch(type)
206        {
207        case OBJ:
208          if (param1)
209            tmpResource->modelSize = *(float*)param1;
210          else
211            tmpResource->modelSize = 1.0;
212
213          if(isFile(fullName))
214            tmpResource->pointer = new OBJModel(fullName, tmpResource->modelSize);
215          else
216            {
217              PRINTF(2)("Sorry, %s does not exist. Loading a cube-Model instead\n", fullName);
218              tmpResource->pointer = ResourceManager::load("cube", PRIM, prio, &tmpResource->modelSize);
219            }
220          break;
221        case PRIM:
222          if (param1)
223            tmpResource->modelSize = *(float*)param1;
224          else
225            tmpResource->modelSize = 1.0;
226
227          if (!strcmp(tmpResource->name, "cube"))
228            tmpResource->pointer = new PrimitiveModel(CUBE, tmpResource->modelSize);
229          else if (!strcmp(tmpResource->name, "sphere"))
230            tmpResource->pointer = new PrimitiveModel(SPHERE, tmpResource->modelSize);
231          else if (!strcmp(tmpResource->name, "plane"))
232            tmpResource->pointer = new PrimitiveModel(PLANE, tmpResource->modelSize);
233          else if (!strcmp(tmpResource->name, "cylinder"))
234            tmpResource->pointer = new PrimitiveModel(CYLINDER, tmpResource->modelSize);
235          else if (!strcmp(tmpResource->name, "cone"))
236            tmpResource->pointer = new PrimitiveModel(CONE, tmpResource->modelSize);
237          break;
238        case TTF:
239            if (param1)
240              tmpResource->ttfSize = *(int*)param1;
241            else
242              tmpResource->ttfSize = FONT_DEFAULT_SIZE;
243            if (param2)
244              {
245                Vector* tmpVec = (Vector*)param2;
246                tmpResource->ttfColorR = (int)tmpVec->x;
247                tmpResource->ttfColorG = (int)tmpVec->y;
248                tmpResource->ttfColorB = (int)tmpVec->z;
249              }
250            else
251              {
252                tmpResource->ttfColorR = FONT_DEFAULT_COLOR_R;
253                tmpResource->ttfColorG = FONT_DEFAULT_COLOR_G;
254                tmpResource->ttfColorB = FONT_DEFAULT_COLOR_B;
255              }
256           
257          if(isFile(fullName))
258            tmpResource->pointer = new Font(fullName,
259                                            tmpResource->ttfSize,
260                                            tmpResource->ttfColorR,
261                                            tmpResource->ttfColorG,
262                                            tmpResource->ttfColorB);
263          else
264            PRINTF(2)("Sorry, %s does not exist. Not loading Font\n", fullName);
265          break;
266        case IMAGE:
267          if(isFile(fullName))
268            {
269              PRINTF(4)("Image %s resides to %s\n", fileName, fullName);
270              tmpResource->pointer = new Texture(fullName);
271            }
272          else
273            {
274              tIterator<char>* iterator = imageDirs->getIterator();
275              tmpDir = iterator->nextElement();
276              //tmpDir = imageDirs->enumerate();
277              while(tmpDir)
278                {
279                  char* imgName = new char[strlen(tmpDir)+strlen(fileName)+1];
280                  sprintf(imgName, "%s%s", tmpDir, fileName);
281                  if(isFile(imgName))
282                    {
283                      PRINTF(4)("Image %s resides to %s\n", fileName, imgName);
284                      tmpResource->pointer = new Texture(imgName);
285                      delete []imgName;
286                      break;
287                    }
288                  delete []imgName;
289                  tmpDir = iterator->nextElement();
290                }
291              delete iterator;
292            }
293          if(!tmpResource)
294             PRINTF(2)("!!Image %s not Found!!\n", fileName);
295          break;
296        default:
297          tmpResource->pointer = NULL;
298          PRINTF(1)("No type found for %s.\n   !!This should not happen unless the Type is not supported yet.!!\n", tmpResource->name);
299          break;
300        }
301      this->resourceList->add(tmpResource);
302      delete []fullName;
303    }
304  if (tmpResource->pointer)
305    return tmpResource->pointer;
306  else 
307    {
308      PRINTF(2)("Resource %s could not be loaded\n", fileName);
309      delete tmpResource;
310      return NULL;
311    }
312}
313
314/**
315   \brief unloads a Resource
316   \param pointer The pointer to free
317   \returns true if successful (pointer found, and deleted), false otherwise
318   
319*/
320bool ResourceManager::unload(void* pointer, ResourcePriority prio)
321{
322  // if pointer is existent. and only one resource of this type exists.
323  Resource* tmpResource = this->locateResourceByPointer(pointer);
324  if (!tmpResource)
325    {
326      PRINTF(2)("Resource not Found %p\n", pointer);
327      return false;
328    }
329  else
330    unload(tmpResource, prio);
331}
332
333bool ResourceManager::unload(Resource* resource, ResourcePriority prio)
334{
335  if (resource->count > 0)
336    resource->count--;
337  if (resource->prio <= prio)
338    {
339      if (resource->count <= 0)
340        {
341          // deleting the Resource
342          switch(resource->type)
343            {
344            case OBJ:
345            case PRIM:
346              delete (Model*)resource->pointer;
347              break;
348            case IMAGE:
349              delete (Texture*)resource->pointer;
350              break;
351            case TTF:
352              delete (Font*)resource->pointer;
353              break;
354            default:
355              PRINTF(1)("NOT YET IMPLEMENTED !!FIX FIX!!\n");
356              return false;
357              break;
358            }
359          // deleting the List Entry:
360          PRINTF(4)("Resource %s safely removed.\n", resource->name);
361          delete []resource->name;
362          this->resourceList->remove(resource);
363        }
364      else
365        PRINTF(4)("Resource %s not removed, because there are still %d References to it.\n", resource->name, resource->count);
366    }
367  else
368    PRINTF(4)("not deleting resource %s because DeleteLevel to high\n", resource->name);
369  return true;
370}
371
372
373/**
374   \brief unloads all alocated Memory of Resources with a pririty lower than prio
375   \param prio The priority to delete
376*/
377bool ResourceManager::unloadAllByPriority(ResourcePriority prio)
378{
379  tIterator<Resource>* iterator = resourceList->getIterator();
380  Resource* enumRes = iterator->nextElement();
381  while (enumRes)
382    {
383      if (enumRes->prio <= prio)
384        if (enumRes->count == 0)
385          unload(enumRes, prio);
386        else
387          PRINTF(2)("unable to unload %s because there are still %d references to it\n",
388                   enumRes->name, enumRes->count);
389      //enumRes = resourceList->nextElement();
390      enumRes = iterator->nextElement();
391    }
392  delete iterator;
393}
394
395/**
396   \brief Searches for a Resource by some information
397   \param fileName The name to look for
398   \returns a Pointer to the Resource if found, NULL otherwise.
399*/
400Resource* ResourceManager::locateResourceByInfo(const char* fileName, ResourceType type, void* param1, void* param2, void* param3)
401{
402  //  Resource* enumRes = resourceList->enumerate();
403  tIterator<Resource>* iterator = resourceList->getIterator();
404  Resource* enumRes = iterator->nextElement();
405  while (enumRes)
406    {
407      if (enumRes->type == type && !strcmp(fileName, enumRes->name))
408        {
409          bool match = false;
410          bool subMatch = false;
411          switch (type)
412            {
413            case PRIM:
414            case OBJ:
415              if (!param1)
416                {
417                  if (enumRes->modelSize == 1.0)
418                    match = true;
419                }
420              else if (enumRes->modelSize == *(float*)param1)
421                match = true;
422              break;
423            case TTF:
424              if (!param1)
425                {
426                  if (enumRes->ttfSize == FONT_DEFAULT_SIZE)
427                    subMatch = true;
428                }
429              else if (enumRes->modelSize =- *(int*)param1)
430                subMatch = true;
431              if(subMatch)
432                {
433                  Vector* tmpVec = (Vector*)param2;
434                  if (!param2)
435                    {
436                      if(enumRes->ttfColorR == FONT_DEFAULT_COLOR_R &&
437                         enumRes->ttfColorG == FONT_DEFAULT_COLOR_G &&
438                         enumRes->ttfColorB == FONT_DEFAULT_COLOR_B )
439                        match = true;
440                    }
441                  else if (enumRes->ttfColorR == (int)tmpVec->x &&
442                           enumRes->ttfColorG == (int)tmpVec->y &&
443                           enumRes->ttfColorB == (int)tmpVec->z )
444                    match = true;
445                }
446
447              break;
448            default:
449              match = true;
450              break;
451            }
452          if (match)
453            {
454              delete iterator;
455              return enumRes;
456            }
457        }
458      enumRes = iterator->nextElement();
459    }
460  delete iterator;
461  return NULL;
462}
463
464/**
465   \brief Searches for a Resource by Pointer
466   \param pointer the Pointer to search for
467   \returns a Pointer to the Resource if found, NULL otherwise.
468*/
469Resource* ResourceManager::locateResourceByPointer(const void* pointer)
470{
471  //  Resource* enumRes = resourceList->enumerate();
472  tIterator<Resource>* iterator = resourceList->getIterator();
473  Resource* enumRes = iterator->nextElement();
474  while (enumRes)
475    {
476      if (pointer == enumRes->pointer)
477        {
478          delete iterator;
479          return enumRes;
480        }
481      enumRes = iterator->nextElement();
482    }
483  delete iterator;
484  return NULL;
485}
486
487/**
488   \brief Checks if it is a Directory
489   \param directoryName the Directory to check for
490   \returns true if it is a directory/symlink false otherwise
491*/
492bool ResourceManager::isDir(const char* directoryName)
493{
494  char* tmpDirName = NULL;
495  struct stat status;
496
497  // checking for the termination of the string given. If there is a "/" at the end cut it away
498  if (directoryName[strlen(directoryName)-1] == '/')
499    {
500      tmpDirName = new char[strlen(directoryName)+1];
501      strncpy(tmpDirName, directoryName, strlen(directoryName)-1);
502      tmpDirName[strlen(directoryName)-1] = '\0';
503    }
504  else
505    {
506      tmpDirName = new char[strlen(directoryName)+1];
507      strcpy(tmpDirName, directoryName);
508    }
509
510  stat(tmpDirName, &status);
511  if (status.st_mode & (S_IFDIR
512#ifndef __WIN32__
513                        | S_IFLNK
514#endif
515                        ))
516    {
517      delete tmpDirName;
518      return true;
519    }
520  else
521    {
522      delete tmpDirName;
523      return false;
524    }
525}
526
527/**
528   \brief Checks if the file is either a Regular file or a Symlink
529   \param fileName the File to check for
530   \returns true if it is a regular file/symlink, false otherwise
531*/
532bool ResourceManager::isFile(const char* fileName)
533{
534  struct stat status;
535  stat(fileName, &status);
536  if (status.st_mode & (S_IFREG
537#ifndef __WIN32__
538                        | S_IFLNK
539#endif
540                        ))
541    return true;
542  else
543    return false;
544}
545
546/**
547   \brief outputs debug information about the ResourceManager
548*/
549void ResourceManager::debug(void)
550{
551  PRINT(0)("=RM===================================\n");
552  PRINT(0)("= RESOURCE-MANAGER DEBUG INFORMATION =\n");
553  PRINT(0)("======================================\n");
554  // if it is not initialized
555  PRINT(0)(" Reference is: %p\n", ResourceManager::singletonRef);
556  PRINT(0)(" Data-Directory is: %s\n", this->dataDir);
557  PRINT(0)(" List of Image-Directories: ");
558  tIterator<char>* tmpIt = imageDirs->getIterator();
559  char* tmpDir = tmpIt->nextElement();
560  while(tmpDir)
561    {
562      PRINT(0)("%s ",tmpDir);
563      tmpDir = tmpIt->nextElement();
564    }
565  delete tmpIt;
566  PRINT(0)("\n");
567
568  PRINT(0)("List of all stored Resources:\n");
569  tIterator<Resource>* iterator = resourceList->getIterator();
570  Resource* enumRes = iterator->nextElement();
571  while (enumRes)
572    {
573      PRINT(0)("-----------------------------------------\n");
574      PRINT(0)("Name: %s; References: %d; Type:", enumRes->name, enumRes->count);
575      switch (enumRes->type)
576        {
577        case OBJ:
578          PRINT(0)("ObjectModel\n");
579          break;
580        case PRIM:
581          PRINT(0)("PrimitiveModel\n");
582          break;
583        case IMAGE:
584          PRINT(0)("ImageFile (Texture)\n");
585          break;
586        default:
587          PRINT(0)("SoundFile\n");
588          break;
589        }
590      PRINT(0)("gets deleted at ");
591      switch(enumRes->prio)
592        {
593        default:
594        case RP_NO:
595          PRINT(0)("first posibility (0)\n");
596          break;
597        case RP_LEVEL:
598          PRINT(0)("the end of the Level (1)\n");
599          break;
600        case RP_CAMPAIGN:
601          PRINT(0)("the end of the campaign (2)\n");
602          break;
603        case RP_GAME:
604          PRINT(0)("when leaving the game (3)\n");
605          break;
606        }
607      enumRes = iterator->nextElement();
608    }
609  delete iterator;
610
611
612
613  PRINT(0)("==================================RM==\n");
614}
Note: See TracBrowser for help on using the repository browser.