Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/orxonox/branches/md2_loader/src/util/resource_manager.cc @ 4065

Last change on this file since 4065 was 4065, checked in by patrick, 19 years ago

branches/md2_importer: just creted the files, started implementing a fps counter

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