Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: copy Resources from the ResourceManger (this is not as safe as with smart-pointers :( )

maybe implement:
http://ootips.org/yonat/4dev/counted_ptr.h

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