Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 4081 was 4033, checked in by bensch, 20 years ago

orxonox/trunk: better support, but it only starts gui, if orxonox crashed, and did not end normaly

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