Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/branches/shared_lib/src/util/loading/resource_manager.cc @ 7174

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

orxonox/dylib: now the dylibLoader should work

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