Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: built two new functions for the NETWORK precache

fromResourceableStrin and toResourceableString

these two functions can be used to CACHE a Resource loaded on one Machine on the other one

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