Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/orxonox/branches/openAL/src/util/resource_manager.cc @ 4204

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

orxonox/branches/openAL: added Buffer to the ResourceManager

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