Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 6640 was 6640, checked in by bensch, 18 years ago

trunk: ResourceManager: make the ResourceManager more modular

File size: 27.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#include "debug.h"
21
22#include <algorithm>
23
24// different resource Types
25#ifndef NO_MODEL
26#include "objModel.h"
27#include "primitive_model.h"
28#include "md2Model.h"
29#endif /* NO_MODEL */
30#ifndef NO_TEXTURES
31#include "texture.h"
32#endif /* NO_TEXTURES */
33#ifndef NO_TEXT
34#include "font.h"
35#endif /* NO_TEXT */
36#ifndef NO_AUDIO
37#include "sound_buffer.h"
38#include "ogg_player.h"
39#endif /* NO_AUDIO */
40#ifndef NO_SHADERS
41#include "shader.h"
42#endif /* NO_SHADERS */
43
44// File Handling Includes
45#include <sys/types.h>
46#include <sys/stat.h>
47#include <unistd.h>
48
49using namespace std;
50
51/**
52 *  standard constructor
53*/
54ResourceManager::ResourceManager ()
55{
56  this->setClassID(CL_RESOURCE_MANAGER, "ResourceManager");
57  this->setName("ResourceManager");
58
59  this->dataDir = new char[3];
60  strcpy(this->dataDir, "./");
61  this->tryDataDir("./data");
62}
63
64//! Singleton Reference to the ResourceManager
65ResourceManager* ResourceManager::singletonRef = NULL;
66
67/**
68 *  standard destructor
69*/
70ResourceManager::~ResourceManager ()
71{
72  // deleting the Resources-List
73  this->unloadAllByPriority(RP_GAME);
74
75  if (!this->resourceList.empty())
76    PRINTF(1)("Not removed all Resources, since there are still %d resources registered\n", this->resourceList.size());
77
78  // deleting the Directorie Lists
79  while (!this->imageDirs.empty())
80  {
81    delete[] this->imageDirs.front();
82    this->imageDirs.pop_front();
83  }
84
85  delete[] this->dataDir;
86
87  ResourceManager::singletonRef = NULL;
88}
89
90/**
91 *  sets the data main directory
92 * @param dataDir the DataDirectory.
93 */
94bool ResourceManager::setDataDir(const char* dataDir)
95{
96  char* realDir = ResourceManager::homeDirCheck(dataDir);
97  if (isDir(realDir))
98  {
99    delete[] this->dataDir;
100    if (dataDir[strlen(dataDir)-1] == '/' || dataDir[strlen(dataDir)-1] == '\\')
101    {
102      this->dataDir = new char[strlen(realDir)+1];
103      strcpy(this->dataDir, realDir);
104    }
105    else
106    {
107      this->dataDir = new char[strlen(realDir)+2];
108      strcpy(this->dataDir, realDir);
109      this->dataDir[strlen(realDir)] = '/';
110      this->dataDir[strlen(realDir)+1] = '\0';
111    }
112    delete[] realDir;
113    return true;
114  }
115  else
116  {
117    PRINTF(1)("%s is not a Directory, and can not be the Data Directory, leaving as %s \n", realDir, this->dataDir);
118    delete[] realDir;
119    return false;
120  }
121}
122
123/**
124 * sets the data main directory
125 * @param dataDir the DataDirectory.
126 *
127 * this is essentially the same as setDataDir, but it ommits the error-message
128 */
129bool ResourceManager::tryDataDir(const char* dataDir)
130{
131  char* realDir = ResourceManager::homeDirCheck(dataDir);
132  if (isDir(realDir))
133  {
134    delete[] this->dataDir;
135    if (dataDir[strlen(dataDir)-1] == '/' || dataDir[strlen(dataDir)-1] == '\\')
136    {
137      this->dataDir = new char[strlen(realDir)+1];
138      strcpy(this->dataDir, realDir);
139    }
140    else
141    {
142      this->dataDir = new char[strlen(realDir)+2];
143      strcpy(this->dataDir, realDir);
144      this->dataDir[strlen(realDir)] = '/';
145      this->dataDir[strlen(realDir)+1] = '\0';
146    }
147    delete[] realDir;
148    return true;
149  }
150  delete[] realDir;
151  return false;
152}
153
154
155
156/**
157 * checks for the DataDirectory, by looking if
158 * @param fileInside is iniside of the given directory.
159*/
160bool ResourceManager::verifyDataDir(const char* fileInside)
161{
162  bool retVal;
163  if (!isDir(this->dataDir))
164  {
165    PRINTF(1)("%s is not a directory\n", this->dataDir);
166    return false;
167  }
168
169  char* testFile = new char[strlen(this->dataDir)+strlen(fileInside)+1];
170  sprintf(testFile, "%s%s", this->dataDir, fileInside);
171  retVal = isFile(testFile);
172  delete[] testFile;
173  return retVal;
174}
175
176#ifndef NO_TEXTURES
177/**
178 *  adds a new Path for Images
179 * @param imageDir The path to insert
180 * @returns true, if the Path was well and injected (or already existent within the list)
181   false otherwise
182*/
183bool ResourceManager::addImageDir(const char* imageDir)
184{
185  if (imageDir == NULL)
186    return false;
187
188  char* newDir;
189  if (imageDir[strlen(imageDir)-1] == '/' || imageDir[strlen(imageDir)-1] == '\\')
190  {
191    newDir = new char[strlen(imageDir)+1];
192    strcpy(newDir, imageDir);
193  }
194  else
195  {
196    newDir = new char[strlen(imageDir)+2];
197    strcpy(newDir, imageDir);
198    newDir[strlen(imageDir)] = '/';
199    newDir[strlen(imageDir)+1] = '\0';
200  }
201  // check if the param is a Directory
202  if (isDir(newDir))
203  {
204    // check if the Directory has been added before
205    std::list<char*>::const_iterator imageDir;
206    for (imageDir = this->imageDirs.begin(); imageDir != this->imageDirs.end(); imageDir++)
207    {
208      if (!strcmp(*imageDir, newDir))
209      {
210        PRINTF(3)("Path %s already loaded\n", newDir);
211        delete[] newDir;
212        return true;
213      }
214    }
215    // adding the directory to the List
216    this->imageDirs.push_back(newDir);
217    return true;
218  }
219  else
220  {
221    PRINTF(1)("%s is not a Directory, and can not be added to the Paths of Images\n", newDir);
222    delete[] newDir;
223    return false;
224  }
225}
226#endif /* NO_TEXTURES */
227
228/**
229 *  loads resources
230 * @param fileName: The fileName of the resource to load
231 * @param prio: The ResourcePriority of this resource (will only be increased)
232 * @param param1: an additional option to parse (see the constuctors for more help)
233 * @param param2: an additional option to parse (see the constuctors for more help)
234 * @param param3: an additional option to parse (see the constuctors for more help)
235 * @returns a pointer to a desired Resource.
236*/
237BaseObject* ResourceManager::load(const char* fileName, ResourcePriority prio, void* param1, void* param2, void* param3)
238{
239  if (fileName == NULL)
240    return NULL;
241  ResourceType tmpType;
242#ifndef NO_MODEL
243#define __IF_OK
244  if (!strncasecmp(fileName+(strlen(fileName)-4), ".obj", 4))
245    tmpType = OBJ;
246  else if (!strncmp(fileName+(strlen(fileName)-4), ".md2", 4))
247    tmpType = MD2;
248  else if (!strcasecmp(fileName, "cube") ||
249           !strcasecmp(fileName, "sphere") ||
250           !strcasecmp(fileName, "plane") ||
251           !strcasecmp(fileName, "cylinder") ||
252           !strcasecmp(fileName, "cone"))
253    tmpType = PRIM;
254#endif /* NO_MODEL */
255#ifndef NO_AUDIO
256#ifdef __IF_OK
257  else
258#endif
259#define __IF_OK
260    if (!strncasecmp(fileName+(strlen(fileName)-4), ".wav", 4))
261      tmpType = WAV;
262    else if (!strncasecmp(fileName+(strlen(fileName)-4), ".mp3", 4))
263      tmpType = MP3;
264    else if (!strncasecmp(fileName+(strlen(fileName)-4), ".ogg", 4))
265      tmpType = OGG;
266#endif /* NO_AUDIO */
267#ifndef NO_TEXT
268#ifdef __IF_OK
269    else
270#endif
271#define __IF_OK
272      if (!strncasecmp(fileName+(strlen(fileName)-4), ".ttf", 4))
273        tmpType = TTF;
274#endif /* NO_TEXT */
275#ifndef NO_SHADERS
276#ifdef __IF_OK
277      else
278#endif
279#define __IF_OK
280        if (!strncasecmp(fileName+(strlen(fileName)-5), ".vert", 5))
281          tmpType = SHADER;
282#endif /* NO_SHADERS */
283#ifndef NO_TEXTURES
284#ifdef __IF_OK
285        else
286#else
287  if
288#endif
289          tmpType = IMAGE;
290#endif /* NO_TEXTURES */
291#undef __IF_OK
292  return this->load(fileName, tmpType, prio, param1, param2, param3);
293}
294
295/**
296 * loads resources
297 * @param fileName: The fileName of the resource to load
298 * @param type: The Type of Resource to load.
299 * @param prio: The ResourcePriority of this resource (will only be increased)
300 * @param param1: an additional option to parse (see the constuctors for more help)
301 * @param param2: an additional option to parse (see the constuctors for more help)
302 * @param param3: an additional option to parse (see the constuctors for more help)
303 * @returns a pointer to a desired Resource.
304*/
305BaseObject* ResourceManager::load(const char* fileName, ResourceType type, ResourcePriority prio,
306                                  void* param1, void* param2, void* param3)
307{
308  assert(fileName != NULL);
309
310  // searching if the resource was loaded before.
311  Resource* tmpResource;
312  // check if we already loaded this Resource
313  tmpResource = this->locateResourceByInfo(fileName, type, param1, param2, param3);
314  // otherwise load it
315  if (tmpResource == NULL)
316    tmpResource = this->loadResource(fileName, type, prio, param1, param2, param3);
317  // return cached pointer.
318  if (tmpResource != NULL) // if the resource was loaded before.
319  {
320    tmpResource->count++;
321    if(tmpResource->prio < prio)
322      tmpResource->prio = prio;
323    return tmpResource->pointer;
324  }
325  else
326    return NULL;
327}
328
329
330/**
331 * loads resources for internal purposes
332 * @param fileName: The fileName of the resource to load
333 * @param type: The Type of Resource to load.
334 * @param prio: The ResourcePriority of this resource (will only be increased)
335 * @param param1: an additional option to parse (see the constuctors for more help)
336 * @param param2: an additional option to parse (see the constuctors for more help)
337 * @param param3: an additional option to parse (see the constuctors for more help)
338 * @returns a pointer to a desired Resource.
339 */
340Resource* ResourceManager::loadResource(const char* fileName, ResourceType type, ResourcePriority prio,
341    void* param1, void* param2, void* param3)
342{
343  // Setting up the new Resource
344  Resource* tmpResource = new Resource;
345  tmpResource->count = 0;
346  tmpResource->type = type;
347  tmpResource->prio = prio;
348  tmpResource->pointer = NULL;
349  tmpResource->name = new char[strlen(fileName)+1];
350  strcpy(tmpResource->name, fileName);
351
352  // creating the full name. (directoryName + FileName)
353  char* fullName = ResourceManager::getFullName(fileName);
354  // Checking for the type of resource \see ResourceType
355  switch(type)
356  {
357#ifndef NO_MODEL
358  case OBJ:
359    if (param1)
360      tmpResource->modelSize = *(float*)param1;
361    else
362      tmpResource->modelSize = 1.0;
363
364    if(ResourceManager::isFile(fullName))
365      tmpResource->pointer = new OBJModel(fullName, tmpResource->modelSize);
366    else
367    {
368      PRINTF(2)("File %s in %s does not exist. Loading a cube-Model instead\n", fileName, dataDir);
369      tmpResource->pointer = ResourceManager::load("cube", PRIM, prio, &tmpResource->modelSize);
370    }
371    break;
372  case PRIM:
373    if (param1)
374      tmpResource->modelSize = *(float*)param1;
375    else
376      tmpResource->modelSize = 1.0;
377
378    if (!strcmp(tmpResource->name, "cube"))
379      tmpResource->pointer = new PrimitiveModel(PRIM_CUBE, tmpResource->modelSize);
380    else if (!strcmp(tmpResource->name, "sphere"))
381      tmpResource->pointer = new PrimitiveModel(PRIM_SPHERE, tmpResource->modelSize);
382    else if (!strcmp(tmpResource->name, "plane"))
383      tmpResource->pointer = new PrimitiveModel(PRIM_PLANE, tmpResource->modelSize);
384    else if (!strcmp(tmpResource->name, "cylinder"))
385      tmpResource->pointer = new PrimitiveModel(PRIM_CYLINDER, tmpResource->modelSize);
386    else if (!strcmp(tmpResource->name, "cone"))
387      tmpResource->pointer = new PrimitiveModel(PRIM_CONE, tmpResource->modelSize);
388    break;
389  case MD2:
390    if(ResourceManager::isFile(fullName))
391    {
392      if (param1 != NULL)
393      {
394        tmpResource->secFileName = new char[strlen((const char*)param1)+1];
395        strcpy(tmpResource->secFileName, (const char*) param1);
396      }
397      else
398        tmpResource->secFileName = NULL;
399      tmpResource->pointer = new MD2Data(fullName, tmpResource->secFileName);
400      //               tmpResource->pointer = new MD2Model(fullName, tmpResource->secFileName);
401
402    }
403    break;
404#endif /* NO_MODEL */
405#ifndef NO_TEXT
406  case TTF:
407    if (param1 != NULL)
408      tmpResource->ttfSize = *(unsigned int*)param1;
409    else
410      tmpResource->ttfSize = FONT_DEFAULT_RENDER_SIZE;
411
412    if(isFile(fullName))
413      tmpResource->pointer = new Font(fullName, tmpResource->ttfSize);
414    else
415      PRINTF(2)("%s does not exist in %s. Not loading Font\n", fileName, this->dataDir);
416    break;
417#endif /* NO_TEXT */
418#ifndef NO_AUDIO
419  case WAV:
420    if(isFile(fullName))
421      tmpResource->pointer = new SoundBuffer(fullName);
422    break;
423  case OGG:
424    if (isFile(fullName))
425      tmpResource->pointer = new OggPlayer(fullName);
426    break;
427#endif /* NO_AUDIO */
428#ifndef NO_TEXTURES
429  case IMAGE:
430    if (param1 != NULL)
431      tmpResource->texTarget = *(GLenum*)param1;
432    else
433      tmpResource->texTarget = GL_TEXTURE_2D;
434    if(isFile(fullName))
435    {
436      PRINTF(4)("Image %s resides to %s\n", fileName, fullName);
437      tmpResource->pointer = new Texture(fullName);
438    }
439    else
440    {
441      std::list<char*>::iterator imageDir;
442      for (imageDir = this->imageDirs.begin(); imageDir != this->imageDirs.end(); imageDir++)
443      {
444        char* imgName = new char[strlen(*imageDir)+strlen(fileName)+1];
445        sprintf(imgName, "%s%s", *imageDir, fileName);
446        if(isFile(imgName))
447        {
448          PRINTF(4)("Image %s resides to %s\n", fileName, imgName);
449          tmpResource->pointer = new Texture(imgName, tmpResource->texTarget);
450          delete[] imgName;
451          break;
452        }
453        delete[] imgName;
454      }
455    }
456    if(!tmpResource)
457      PRINTF(2)("!!Image %s not Found!!\n", fileName);
458    break;
459#endif /* NO_TEXTURES */
460#ifndef NO_SHADERS
461  case SHADER:
462    if(ResourceManager::isFile(fullName))
463    {
464      if (param1 != NULL)
465      {
466        char* secFullName = ResourceManager::getFullName((const char*)param1);
467        if (ResourceManager::isFile(secFullName))
468        {
469          tmpResource->secFileName = new char[strlen((const char*)param1)+1];
470          strcpy(tmpResource->secFileName, (const char*) param1);
471          tmpResource->pointer = new Shader(fullName, secFullName);
472        }
473        delete[] secFullName;
474      }
475      else
476      {
477        tmpResource->secFileName = NULL;
478        tmpResource->pointer = new Shader(fullName, NULL);
479      }
480    }
481    break;
482#endif /* NO_SHADERS */
483  default:
484    tmpResource->pointer = NULL;
485    PRINTF(1)("No type found for %s.\n   !!This should not happen unless the Type is not supported yet. JUST DO IT!!\n", tmpResource->name);
486    break;
487  }
488  if (tmpResource->pointer != NULL)
489    this->resourceList.push_back(tmpResource);
490  delete[] fullName;
491
492
493  if (tmpResource->pointer != NULL)
494    return tmpResource;
495  else
496  {
497    PRINTF(2)("Resource %s could not be loaded\n", fileName);
498    delete[] tmpResource->name;
499    delete tmpResource;
500    return NULL;
501  }
502}
503
504/**
505 * unloads a Resource
506 * @param pointer: The pointer to free
507 * @param prio: the PriorityLevel to unload this resource
508 * @returns true if successful (pointer found, and deleted), false otherwise
509*/
510bool ResourceManager::unload(void* pointer, ResourcePriority prio)
511{
512  if (pointer == NULL)
513    return false;
514  // if pointer is existent. and only one resource of this type exists.
515  Resource* tmpResource = this->locateResourceByPointer(pointer);
516  if (tmpResource != NULL)
517    return unload(tmpResource, prio);
518  else
519  {
520    PRINTF(2)("Resource not Found %p\n", pointer);
521    return false;
522  }
523}
524
525/**
526 * unloads a Resource
527 * @param resource: The resource to unloade
528 * @param prio the PriorityLevel to unload this resource
529 * @returns true on success, false otherwise.
530*/
531bool ResourceManager::unload(Resource* resource, ResourcePriority prio)
532{
533  if (resource == NULL)
534    return false;
535  if (resource->count > 0)
536    resource->count--;
537
538  if (resource->prio <= prio)
539  {
540    if (resource->count == 0)
541    {
542      // deleting the Resource
543      switch(resource->type)
544      {
545#ifndef NO_MODEL
546      case OBJ:
547      case PRIM:
548        delete (Model*)resource->pointer;
549        break;
550      case MD2:
551        delete (MD2Data*)resource->pointer;
552        break;
553#endif /* NO_MODEL */
554#ifndef NO_AUDIO
555      case WAV:
556        delete (SoundBuffer*)resource->pointer;
557        break;
558      case OGG:
559        delete (OggPlayer*)resource->pointer;
560        break;
561#endif /* NO_AUDIO */
562#ifndef NO_TEXT
563      case TTF:
564        delete (Font*)resource->pointer;
565        break;
566#endif /* NO_TEXT */
567#ifndef NO_TEXTURES
568      case IMAGE:
569        delete (Texture*)resource->pointer;
570        break;
571#endif /* NO_TEXTURES */
572#ifndef NO_SHADERS
573      case SHADER:
574        delete (Shader*)resource->pointer;
575        break;
576#endif /* NO_SHADERS */
577      default:
578        PRINTF(2)("NOT YET IMPLEMENTED !!FIX FIX!!\n");
579        return false;
580        break;
581      }
582      // deleting the List Entry:
583      PRINTF(4)("Resource %s safely removed.\n", resource->name);
584      delete[] resource->name;
585      std::list<Resource*>::iterator resourceIT = std::find(this->resourceList.begin(), this->resourceList.end(), resource);
586      this->resourceList.erase(resourceIT);
587      delete resource;
588    }
589    else
590      PRINTF(4)("Resource %s not removed, because there are still %d References to it.\n", resource->name, resource->count);
591  }
592  else
593    PRINTF(4)("not deleting resource %s because DeleteLevel to high\n", resource->name);
594  return true;
595}
596
597
598/**
599 * unloads all alocated Memory of Resources with a pririty lower than prio
600 * @param prio The priority to delete
601*/
602bool ResourceManager::unloadAllByPriority(ResourcePriority prio)
603{
604  std::list<Resource*>::iterator resource, pre;
605  pre = --this->resourceList.end();
606  unsigned int removeCount;
607  for (unsigned int round = 0; round < 3; round++)
608  {
609    removeCount = 0;
610    while (pre != resourceList.end())
611    {
612      resource = pre;
613      pre--;
614      if ((*resource)->prio <= prio)
615      {
616        if ((*resource)->count == 0)
617          unload((*resource), prio);
618        else
619        {
620          PRINTF(2)("unable to unload %s because there are still %d references to it\n",
621                    (*resource)->name, (*resource)->count);
622          removeCount++;
623        }
624      }
625    }
626    if (removeCount == 0) break;
627  }
628}
629
630
631/**
632 * Searches for a Resource by some information
633 * @param fileName: The name to look for
634 * @param type the Type of resource to locate.
635 * @param param1: an additional option to parse (see the constuctors for more help)
636 * @param param2: an additional option to parse (see the constuctors for more help)
637 * @param param3: an additional option to parse (see the constuctors for more help)
638 * @returns a Pointer to the Resource if found, NULL otherwise.
639*/
640Resource* ResourceManager::locateResourceByInfo(const char* fileName, ResourceType type,
641    void* param1, void* param2, void* param3) const
642{
643  std::list<Resource*>::const_iterator resource;
644  for (resource = this->resourceList.begin(); resource != this->resourceList.end(); resource++)
645  {
646    if ((*resource)->type == type && !strcmp(fileName, (*resource)->name))
647    {
648      bool match = false;
649
650      switch (type)
651      {
652#ifndef NO_MODEL
653      case PRIM:
654      case OBJ:
655        if (!param1)
656        {
657          if ((*resource)->modelSize == 1.0)
658            match = true;
659        }
660        else if ((*resource)->modelSize == *(float*)param1)
661          match = true;
662        break;
663      case MD2:
664        if (!param1)
665        {
666          if ((*resource)->secFileName == NULL)
667            match = true;
668        }
669        else if (!strcmp((*resource)->secFileName, (const char*)param1))
670          match = true;
671        break;
672#endif /* NO_MODEL */
673#ifndef NO_TEXT
674      case TTF:
675        if (param1 == NULL)
676        {
677          if ((*resource)->ttfSize == FONT_DEFAULT_RENDER_SIZE)
678            match = true;
679        }
680        else if ((*resource)->ttfSize == *(unsigned int*)param1)
681          match = true;
682        break;
683#endif /* NO_TEXT */
684#ifndef NO_SHADERS
685      case SHADER:
686        if (!param1)
687        {
688          if ((*resource)->secFileName == NULL)
689            match = true;
690        }
691        else if (!strcmp((*resource)->secFileName, (const char*)param1))
692          match = true;
693#endif /* NO_SHADERS */
694#ifndef NO_TEXTURES
695      case IMAGE:
696        if (!param1)
697        {
698          if ((*resource)->texTarget == GL_TEXTURE_2D)
699            match = true;
700        }
701        else if ((*resource)->texTarget ==  *(GLenum*)param1)
702          match = true;
703#endif /* NO_TEXTURES */
704      default:
705        match = true;
706        break;
707      }
708      if (match)
709      {
710        return (*resource);
711      }
712    }
713  }
714  return NULL;
715}
716
717/**
718 * Searches for a Resource by Pointer
719 * @param pointer the Pointer to search for
720 * @returns a Pointer to the Resource if found, NULL otherwise.
721*/
722Resource* ResourceManager::locateResourceByPointer(const void* pointer) const
723{
724  //  Resource* enumRes = resourceList->enumerate();
725  std::list<Resource*>::const_iterator resource;
726  for (resource = this->resourceList.begin(); resource != this->resourceList.end(); resource++)
727    if (pointer == (*resource)->pointer)
728      return (*resource);
729  return NULL;
730}
731
732/**
733 * Checks if it is a Directory
734 * @param directoryName the Directory to check for
735 * @returns true if it is a directory/symlink false otherwise
736*/
737bool ResourceManager::isDir(const char* directoryName)
738{
739  if (directoryName == NULL)
740    return false;
741
742  char* tmpDirName = NULL;
743  struct stat status;
744
745  // checking for the termination of the string given. If there is a "/" at the end cut it away
746  if (directoryName[strlen(directoryName)-1] == '/' ||
747      directoryName[strlen(directoryName)-1] == '\\')
748  {
749    tmpDirName = new char[strlen(directoryName)];
750    strncpy(tmpDirName, directoryName, strlen(directoryName)-1);
751    tmpDirName[strlen(directoryName)-1] = '\0';
752  }
753  else
754  {
755    tmpDirName = new char[strlen(directoryName)+1];
756    strcpy(tmpDirName, directoryName);
757  }
758
759  if(!stat(tmpDirName, &status))
760  {
761    if (status.st_mode & (S_IFDIR
762#ifndef __WIN32__
763                          | S_IFLNK
764#endif
765                         ))
766    {
767      delete[] tmpDirName;
768      return true;
769    }
770    else
771    {
772      delete[] tmpDirName;
773      return false;
774    }
775  }
776  else
777  {
778    delete[] tmpDirName;
779    return false;
780  }
781}
782
783/**
784 * Checks if the file is either a Regular file or a Symlink
785 * @param fileName the File to check for
786 * @returns true if it is a regular file/symlink, false otherwise
787*/
788bool ResourceManager::isFile(const char* fileName)
789{
790  if (fileName == NULL)
791    return false;
792  char* tmpFileName = ResourceManager::homeDirCheck(fileName);
793  // actually checks the File
794  struct stat status;
795  if (!stat(tmpFileName, &status))
796  {
797    if (status.st_mode & (S_IFREG
798#ifndef __WIN32__
799                          | S_IFLNK
800#endif
801                         ))
802    {
803      delete[] tmpFileName;
804      return true;
805    }
806    else
807    {
808      delete[] tmpFileName;
809      return false;
810    }
811  }
812  else
813  {
814    delete[] tmpFileName;
815    return false;
816  }
817}
818
819/**
820 * touches a File on the disk (thereby creating it)
821 * @param fileName The file to touch
822*/
823bool ResourceManager::touchFile(const char* fileName)
824{
825  char* tmpName = ResourceManager::homeDirCheck(fileName);
826  if (tmpName == NULL)
827    return false;
828  FILE* stream;
829  if( (stream = fopen (tmpName, "w")) == NULL)
830  {
831    PRINTF(1)("could not open %s fro writing\n", fileName);
832    delete[] tmpName;
833    return false;
834  }
835  fclose(stream);
836
837  delete[] tmpName;
838}
839
840/**
841 * deletes a File from disk
842 * @param fileName the File to delete
843*/
844bool ResourceManager::deleteFile(const char* fileName)
845{
846  if (fileName == NULL)
847    return false;
848  char* tmpName = ResourceManager::homeDirCheck(fileName);
849  unlink(tmpName);
850  delete[] tmpName;
851}
852
853/**
854 * @param name the Name of the file to check
855 * @returns The name of the file, including the HomeDir
856 * IMPORTANT: this has to be deleted from the outside
857 */
858char* ResourceManager::homeDirCheck(const char* name)
859{
860  if (name == NULL)
861    return NULL;
862  char* retName;
863  if (!strncmp(name, "~/", 2))
864  {
865    char tmpFileName[500];
866#ifdef __WIN32__
867    strcpy(tmpFileName, getenv("USERPROFILE"));
868#else
869    strcpy(tmpFileName, getenv("HOME"));
870#endif
871    retName = new char[strlen(tmpFileName)+strlen(name)];
872    sprintf(retName, "%s%s", tmpFileName, name+1);
873  }
874  else
875  {
876    retName = new char[strlen(name)+1];
877    strcpy(retName, name);
878  }
879  return retName;
880}
881
882/**
883 * @param fileName the Name of the File to check
884 * @returns The full name of the file, including the DataDir, and NULL if the file does not exist
885 * !!IMPORTANT: this has to be deleted from the outside!!
886*/
887char* ResourceManager::getFullName(const char* fileName)
888{
889  if (fileName == NULL || ResourceManager::getInstance()->getDataDir() == NULL)
890    return NULL;
891
892  char* retName = new char[strlen(ResourceManager::getInstance()->getDataDir())
893                           + strlen(fileName) + 1];
894  sprintf(retName, "%s%s", ResourceManager::getInstance()->getDataDir(), fileName);
895  if (ResourceManager::isFile(retName) || ResourceManager::isDir(retName))
896    return retName;
897  else
898  {
899    delete[] retName;
900    return NULL;
901  }
902}
903
904
905/**
906 * checks wether a file is in the DataDir.
907 * @param fileName the File to check if it is in the Data-Dir structure.
908 * @returns true if the file exists, false otherwise
909 */
910bool ResourceManager::isInDataDir(const char* fileName)
911{
912  if (fileName == NULL || ResourceManager::getInstance()->getDataDir() == NULL)
913    return false;
914
915  bool retVal = false;
916  char* checkFile = new char[strlen(ResourceManager::getInstance()->getDataDir())
917                             + strlen(fileName) + 1];
918  sprintf(checkFile, "%s%s", ResourceManager::getInstance()->getDataDir(), fileName);
919
920  if (ResourceManager::isFile(checkFile) || ResourceManager::isDir(checkFile))
921    retVal = true;
922  else
923    retVal = false;
924  delete[] checkFile;
925  return retVal;
926}
927
928
929/**
930 * outputs debug information about the ResourceManager
931*/
932void ResourceManager::debug() const
933{
934  PRINT(0)("=RM===================================\n");
935  PRINT(0)("= RESOURCE-MANAGER DEBUG INFORMATION =\n");
936  PRINT(0)("======================================\n");
937  // if it is not initialized
938  PRINT(0)(" Reference is: %p\n", ResourceManager::singletonRef);
939  PRINT(0)(" Data-Directory is: %s\n", this->dataDir);
940  PRINT(0)(" List of Image-Directories: ");
941  std::list<char*>::const_iterator imageDir;
942  for (imageDir = this->imageDirs.begin(); imageDir != this->imageDirs.end(); imageDir++)
943    PRINT(0)("%s ", (*imageDir));
944  PRINT(0)("\n");
945
946  PRINT(0)("List of all stored Resources:\n");
947  std::list<Resource*>::const_iterator resource;
948  for (resource = this->resourceList.begin(); resource != this->resourceList.end(); resource++)
949
950  {
951    PRINT(0)("-----------------------------------------\n");
952    PRINT(0)("Name: %s; References: %d; Type: %s ", (*resource)->name, (*resource)->count, ResourceManager::ResourceTypeToChar((*resource)->type));
953
954    PRINT(0)("gets deleted at ");
955    switch((*resource)->prio)
956    {
957    default:
958    case RP_NO:
959      PRINT(0)("first posibility (0)\n");
960      break;
961    case RP_LEVEL:
962      PRINT(0)("the end of the Level (1)\n");
963      break;
964    case RP_CAMPAIGN:
965      PRINT(0)("the end of the campaign (2)\n");
966      break;
967    case RP_GAME:
968      PRINT(0)("when leaving the game (3)\n");
969      break;
970    }
971  }
972
973
974
975  PRINT(0)("==================================RM==\n");
976}
977
978
979/**
980 * converts a ResourceType into the corresponding String
981 * @param type the ResourceType to translate
982 * @returns the converted String.
983 */
984const char* ResourceManager::ResourceTypeToChar(ResourceType type)
985{
986  switch (type)
987  {
988#ifndef NO_MODEL
989  case OBJ:
990    return "ObjectModel";
991    break;
992  case PRIM:
993    return "PrimitiveModel";
994    break;
995  case MD2:
996    return "MD2-Data";
997    break;
998#endif
999#ifndef NO_TEXTURES
1000  case IMAGE:
1001    return "ImageFile (Texture)";
1002    break;
1003#endif
1004#ifndef NO_AUDIO
1005  case WAV:
1006    return "SoundFile";
1007    break;
1008  case OGG:
1009    return "MusicFile";
1010    break;
1011#endif
1012#ifndef NO_TEXT
1013  case TTF:
1014    return "Font (TTF)";
1015    break;
1016#endif
1017#ifndef NO_SHADERS
1018  case SHADER:
1019    return "Shader";
1020    break;
1021#endif
1022  default:
1023    return "unknown Format";
1024    break;
1025  }
1026}
Note: See TracBrowser for help on using the repository browser.