Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: resource now also gets loaded if the data-directory is not where it is supposed to be… this will be better in the future (i hope)

File size: 16.3 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 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*/
109bool ResourceManager::addImageDir(char* imageDir)
110{
111  // check if the param is a Directory
112  if (isDir(imageDir))
113    {
114      // check if the Directory has been added before
115      tIterator<char>* tmpImageDirs = imageDirs->getIterator();
116      char* tmpDir = tmpImageDirs->nextElement();
117      while(tmpDir)
118        {
119          if (!strcmp(tmpDir, imageDir))
120            {
121              PRINTF(4)("Path %s already loaded\n", imageDir);
122              delete tmpImageDirs;
123              return true;
124            }
125          tmpDir = tmpImageDirs->nextElement();
126        }
127      delete tmpImageDirs;
128
129      // adding the directory to the List
130      tmpDir  = new char[strlen(imageDir)+1];
131      strcpy(tmpDir, imageDir);
132      this->imageDirs->add(tmpDir);
133      return true;
134    }
135  else
136    {
137      PRINTF(1)("%s is not a Directory, and can not be added to the Paths of Images\n", dataDir);
138      return false;
139    }
140}
141
142/**
143   \brief loads resources
144   \param fileName The fileName of the resource to load
145   \param prio The ResourcePriority of this resource (will only be increased)
146   \returns a pointer to a desired Resource.
147*/
148void* ResourceManager::load(const char* fileName, ResourcePriority prio, void* param1, void* param2, void* param3)
149{
150  ResourceType tmpType;
151  if (!strncmp(fileName+(strlen(fileName)-4), ".obj", 4))
152    tmpType = OBJ;
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;
165  else if (!strncmp(fileName+(strlen(fileName)-4), ".ttf", 4))
166    tmpType = TTF;
167  else 
168    tmpType = IMAGE;
169
170  return this->load(fileName, tmpType, prio, param1, param2, param3);
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)
177   \param prio The ResourcePriority of this resource (will only be increased)
178   \returns a pointer to a desired Resource.
179*/
180void* ResourceManager::load(const char* fileName, ResourceType type, ResourcePriority prio, void* param1, void* param2, void* param3)
181{
182  // searching if the resource was loaded before.
183  Resource* tmpResource = this->locateResourceByInfo(fileName, type, param1, param2,param3);
184  if (tmpResource) // if the resource was not loaded before.
185    {
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    {
193      char* tmpDir;
194      // Setting up the new Resource
195      tmpResource = new Resource;
196      tmpResource->count = 1;
197      tmpResource->type = type;
198      tmpResource->prio = prio;
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];
204      sprintf(fullName, "%s%s", this->dataDir, fileName);
205     
206      // Checking for the type of resource \see ResourceType
207      switch(type)
208        {
209        case OBJ:
210          if (param1)
211            tmpResource->modelSize = *(float*)param1;
212          else
213            tmpResource->modelSize = 1.0;
214
215          if(isFile(fullName))
216            tmpResource->pointer = new OBJModel(fullName, tmpResource->modelSize);
217          else
218            {
219              PRINTF(2)("Sorry, %s does not exist. Loading a cube-Model instead\n", fullName);
220              tmpResource->pointer = ResourceManager::load("cube", PRIM, prio, &tmpResource->modelSize);
221            }
222          break;
223        case PRIM:
224          if (param1)
225            tmpResource->modelSize = *(float*)param1;
226          else
227            tmpResource->modelSize = 1.0;
228
229          if (!strcmp(tmpResource->name, "cube"))
230            tmpResource->pointer = new PrimitiveModel(CUBE, tmpResource->modelSize);
231          else if (!strcmp(tmpResource->name, "sphere"))
232            tmpResource->pointer = new PrimitiveModel(SPHERE, tmpResource->modelSize);
233          else if (!strcmp(tmpResource->name, "plane"))
234            tmpResource->pointer = new PrimitiveModel(PLANE, tmpResource->modelSize);
235          else if (!strcmp(tmpResource->name, "cylinder"))
236            tmpResource->pointer = new PrimitiveModel(CYLINDER, tmpResource->modelSize);
237          else if (!strcmp(tmpResource->name, "cone"))
238            tmpResource->pointer = new PrimitiveModel(CONE, tmpResource->modelSize);
239          break;
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;
268        case IMAGE:
269          if(isFile(fullName))
270            {
271              PRINTF(4)("Image %s resides to %s\n", fileName, fullName);
272              tmpResource->pointer = new Texture(fullName);
273            }
274          else
275            {
276              tIterator<char>* iterator = imageDirs->getIterator();
277              tmpDir = iterator->nextElement();
278              //tmpDir = imageDirs->enumerate();
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))
284                    {
285                      PRINTF(4)("Image %s resides to %s\n", fileName, imgName);
286                      tmpResource->pointer = new Texture(imgName);
287                      delete []imgName;
288                      break;
289                    }
290                  delete []imgName;
291                  tmpDir = iterator->nextElement();
292                }
293              delete iterator;
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;
302        }
303      this->resourceList->add(tmpResource);
304      delete []fullName;
305    }
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    }
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*/
322bool ResourceManager::unload(void* pointer, ResourcePriority prio)
323{
324  // if pointer is existent. and only one resource of this type exists.
325  Resource* tmpResource = this->locateResourceByPointer(pointer);
326  if (!tmpResource)
327    {
328      PRINTF(2)("Resource not Found %p\n", pointer);
329      return false;
330    }
331  else
332    unload(tmpResource, prio);
333}
334
335bool ResourceManager::unload(Resource* resource, ResourcePriority prio)
336{
337  if (resource->count > 0)
338    resource->count--;
339  if (resource->prio <= prio)
340    {
341      if (resource->count <= 0)
342        {
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;
353            case TTF:
354              delete (Font*)resource->pointer;
355              break;
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;
364          this->resourceList->remove(resource);
365        }
366      else
367        PRINTF(4)("Resource %s not removed, because there are still %d References to it.\n", resource->name, resource->count);
368    }
369  else
370    PRINTF(4)("not deleting resource %s because DeleteLevel to high\n", resource->name);
371  return true;
372}
373
374
375/**
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{
381  tIterator<Resource>* iterator = resourceList->getIterator();
382  Resource* enumRes = iterator->nextElement();
383  while (enumRes)
384    {
385      if (enumRes->prio <= prio)
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);
391      //enumRes = resourceList->nextElement();
392      enumRes = iterator->nextElement();
393    }
394  delete iterator;
395}
396
397/**
398   \brief Searches for a Resource by some information
399   \param fileName The name to look for
400   \returns a Pointer to the Resource if found, NULL otherwise.
401*/
402Resource* ResourceManager::locateResourceByInfo(const char* fileName, ResourceType type, void* param1, void* param2, void* param3)
403{
404  //  Resource* enumRes = resourceList->enumerate();
405  tIterator<Resource>* iterator = resourceList->getIterator();
406  Resource* enumRes = iterator->nextElement();
407  while (enumRes)
408    {
409      if (enumRes->type == type && !strcmp(fileName, enumRes->name))
410        {
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            }
459        }
460      enumRes = iterator->nextElement();
461    }
462  delete iterator;
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{
473  //  Resource* enumRes = resourceList->enumerate();
474  tIterator<Resource>* iterator = resourceList->getIterator();
475  Resource* enumRes = iterator->nextElement();
476  while (enumRes)
477    {
478      if (pointer == enumRes->pointer)
479        {
480          delete iterator;
481          return enumRes;
482        }
483      enumRes = iterator->nextElement();
484    }
485  delete iterator;
486  return NULL;
487}
488
489/**
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{
496  char* tmpDirName = NULL;
497  struct stat status;
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
512  stat(tmpDirName, &status);
513  if (status.st_mode & (S_IFDIR
514#ifndef __WIN32__
515                        | S_IFLNK
516#endif
517                        ))
518    {
519      delete tmpDirName;
520      return true;
521    }
522  else
523    {
524      delete tmpDirName;
525      return false;
526    }
527}
528
529/**
530   \brief Checks if the file is either a Regular file or a Symlink
531   \param fileName the File to check for
532   \returns true if it is a regular file/symlink, false otherwise
533*/
534bool ResourceManager::isFile(const char* fileName)
535{
536  struct stat status;
537  stat(fileName, &status);
538  if (status.st_mode & (S_IFREG
539#ifndef __WIN32__
540                        | S_IFLNK
541#endif
542                        ))
543    return true;
544  else
545    return false;
546}
547
548/**
549   \brief outputs debug information about the ResourceManager
550*/
551void ResourceManager::debug(void)
552{
553  PRINT(0)("=RM===================================\n");
554  PRINT(0)("= RESOURCE-MANAGER DEBUG INFORMATION =\n");
555  PRINT(0)("======================================\n");
556  // if it is not initialized
557  PRINT(0)(" Reference is: %p\n", ResourceManager::singletonRef);
558  PRINT(0)(" Data-Directory is: %s\n", this->dataDir);
559  PRINT(0)(" List of Image-Directories: ");
560  tIterator<char>* tmpIt = imageDirs->getIterator();
561  char* tmpDir = tmpIt->nextElement();
562  while(tmpDir)
563    {
564      PRINT(0)("%s ",tmpDir);
565      tmpDir = tmpIt->nextElement();
566    }
567  delete tmpIt;
568  PRINT(0)("\n");
569
570  PRINT(0)("List of all stored Resources:\n");
571  tIterator<Resource>* iterator = resourceList->getIterator();
572  Resource* enumRes = iterator->nextElement();
573  while (enumRes)
574    {
575      PRINT(0)("-----------------------------------------\n");
576      PRINT(0)("Name: %s; References: %d; Type:", enumRes->name, enumRes->count);
577      switch (enumRes->type)
578        {
579        case OBJ:
580          PRINT(0)("ObjectModel\n");
581          break;
582        case PRIM:
583          PRINT(0)("PrimitiveModel\n");
584          break;
585        case IMAGE:
586          PRINT(0)("ImageFile (Texture)\n");
587          break;
588        default:
589          PRINT(0)("SoundFile\n");
590          break;
591        }
592      PRINT(0)("gets deleted at ");
593      switch(enumRes->prio)
594        {
595        default:
596        case RP_NO:
597          PRINT(0)("first posibility (0)\n");
598          break;
599        case RP_LEVEL:
600          PRINT(0)("the end of the Level (1)\n");
601          break;
602        case RP_CAMPAIGN:
603          PRINT(0)("the end of the campaign (2)\n");
604          break;
605        case RP_GAME:
606          PRINT(0)("when leaving the game (3)\n");
607          break;
608        }
609      enumRes = iterator->nextElement();
610    }
611  delete iterator;
612
613
614
615  PRINT(0)("==================================RM==\n");
616}
Note: See TracBrowser for help on using the repository browser.