Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: test was ok… it is not the resourcemanage….. so what could it be in windows…..

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