Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: new style for resources (prework/movement)

File size: 31.2 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 "util/loading/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
66//! Singleton Reference to the ResourceManager
67ResourceManager* ResourceManager::singletonRef = NULL;
68
69/**
70 * @brief standard destructor
71*/
72ResourceManager::~ResourceManager ()
73{
74  // deleting the Resources-List
75  this->unloadAllByPriority(RP_GAME);
76
77  if (!this->resourceList.empty())
78    PRINTF(1)("Not removed all Resources, since there are still %d resources registered\n", this->resourceList.size());
79
80  // deleting the Directorie Lists
81  while (!this->imageDirs.empty())
82  {
83    delete[] this->imageDirs.back();
84    this->imageDirs.pop_back();
85  }
86
87  delete[] this->dataDir;
88
89  ResourceManager::singletonRef = NULL;
90}
91
92/**
93 * @brief sets the data main directory
94 * @param dataDir the DataDirectory.
95 */
96bool ResourceManager::setDataDir(const char* dataDir)
97{
98  char* realDir = ResourceManager::homeDirCheck(dataDir);
99  if (isDir(realDir))
100  {
101    delete[] this->dataDir;
102    if (dataDir[strlen(dataDir)-1] == '/' || dataDir[strlen(dataDir)-1] == '\\')
103    {
104      this->dataDir = new char[strlen(realDir)+1];
105      strcpy(this->dataDir, realDir);
106    }
107    else
108    {
109      this->dataDir = new char[strlen(realDir)+2];
110      strcpy(this->dataDir, realDir);
111      this->dataDir[strlen(realDir)] = '/';
112      this->dataDir[strlen(realDir)+1] = '\0';
113    }
114    delete[] realDir;
115    return true;
116  }
117  else
118  {
119    PRINTF(1)("%s is not a Directory, and can not be the Data Directory, leaving as %s \n", realDir, this->dataDir);
120    delete[] realDir;
121    return false;
122  }
123}
124
125/**
126 * @brief sets the data main directory
127 * @param dataDir the DataDirectory.
128 *
129 * this is essentially the same as setDataDir, but it ommits the error-message
130 */
131bool ResourceManager::tryDataDir(const char* dataDir)
132{
133  char* realDir = ResourceManager::homeDirCheck(dataDir);
134  if (isDir(realDir))
135  {
136    delete[] this->dataDir;
137    if (dataDir[strlen(dataDir)-1] == '/' || dataDir[strlen(dataDir)-1] == '\\')
138    {
139      this->dataDir = new char[strlen(realDir)+1];
140      strcpy(this->dataDir, realDir);
141    }
142    else
143    {
144      this->dataDir = new char[strlen(realDir)+2];
145      strcpy(this->dataDir, realDir);
146      this->dataDir[strlen(realDir)] = '/';
147      this->dataDir[strlen(realDir)+1] = '\0';
148    }
149    delete[] realDir;
150    return true;
151  }
152  delete[] realDir;
153  return false;
154}
155
156
157/**
158 * @brief checks for the DataDirectory, by looking if
159 * @param fileInside is iniside of the given directory.
160*/
161bool ResourceManager::verifyDataDir(const char* fileInside)
162{
163  bool retVal;
164  if (!isDir(this->dataDir))
165  {
166    PRINTF(1)("%s is not a directory\n", this->dataDir);
167    return false;
168  }
169
170  char* testFile = new char[strlen(this->dataDir)+strlen(fileInside)+1];
171  sprintf(testFile, "%s%s", this->dataDir, fileInside);
172  retVal = isFile(testFile);
173  delete[] testFile;
174  return retVal;
175}
176
177#ifndef NO_TEXTURES
178/**
179 * @brief adds a new Path for Images
180 * @param imageDir The path to insert
181 * @returns true, if the Path was well and injected (or already existent within the list)
182   false otherwise
183*/
184bool ResourceManager::addImageDir(const char* imageDir)
185{
186  if (imageDir == NULL)
187    return false;
188
189  char* newDir;
190  if (imageDir[strlen(imageDir)-1] == '/' || imageDir[strlen(imageDir)-1] == '\\')
191  {
192    newDir = new char[strlen(imageDir)+1];
193    strcpy(newDir, imageDir);
194  }
195  else
196  {
197    newDir = new char[strlen(imageDir)+2];
198    strcpy(newDir, imageDir);
199    newDir[strlen(imageDir)] = '/';
200    newDir[strlen(imageDir)+1] = '\0';
201  }
202  // check if the param is a Directory
203  if (isDir(newDir))
204  {
205    // check if the Directory has been added before
206    std::vector<char*>::const_iterator imageDir;
207    for (imageDir = this->imageDirs.begin(); imageDir != this->imageDirs.end(); imageDir++)
208    {
209      if (!strcmp(*imageDir, newDir))
210      {
211        PRINTF(3)("Path %s already loaded\n", newDir);
212        delete[] newDir;
213        return true;
214      }
215    }
216    // adding the directory to the List
217    this->imageDirs.push_back(newDir);
218    return true;
219  }
220  else
221  {
222    PRINTF(1)("%s is not a Directory, and can not be added to the Paths of Images\n", newDir);
223    delete[] newDir;
224    return false;
225  }
226}
227#endif /* NO_TEXTURES */
228
229/**
230 * @brief loads resources
231 * @param fileName: The fileName of the resource to load
232 * @param prio: The ResourcePriority of this resource (will only be increased)
233 * @param param0: an additional option to parse (see the constuctors for more help)
234 * @param param1: an additional option to parse (see the constuctors for more help)
235 * @param param2: an additional option to parse (see the constuctors for more help)
236 * @returns a pointer to a desired Resource.
237*/
238BaseObject* ResourceManager::load(const char* fileName, ResourcePriority prio,
239                                  const MultiType& param0, const MultiType& param1, const MultiType& param2)
240{
241  if (fileName == NULL)
242    return NULL;
243  ResourceType tmpType;
244#ifndef NO_MODEL
245#define __IF_OK
246  if (!strncasecmp(fileName+(strlen(fileName)-4), ".obj", 4))
247    tmpType = OBJ;
248  else if (!strncmp(fileName+(strlen(fileName)-4), ".md2", 4))
249    tmpType = MD2;
250  else if (!strcasecmp(fileName, "cube") ||
251           !strcasecmp(fileName, "sphere") ||
252           !strcasecmp(fileName, "plane") ||
253           !strcasecmp(fileName, "cylinder") ||
254           !strcasecmp(fileName, "cone"))
255    tmpType = PRIM;
256#endif /* NO_MODEL */
257#ifndef NO_AUDIO
258#ifdef __IF_OK
259  else
260#endif
261#define __IF_OK
262    if (!strncasecmp(fileName+(strlen(fileName)-4), ".wav", 4))
263      tmpType = WAV;
264    else if (!strncasecmp(fileName+(strlen(fileName)-4), ".mp3", 4))
265      tmpType = MP3;
266    else if (!strncasecmp(fileName+(strlen(fileName)-4), ".ogg", 4))
267      tmpType = OGG;
268#endif /* NO_AUDIO */
269#ifndef NO_TEXT
270#ifdef __IF_OK
271    else
272#endif
273#define __IF_OK
274      if (!strncasecmp(fileName+(strlen(fileName)-4), ".ttf", 4))
275        tmpType = TTF;
276#endif /* NO_TEXT */
277#ifndef NO_SHADERS
278#ifdef __IF_OK
279      else
280#endif
281#define __IF_OK
282        if (!strncasecmp(fileName+(strlen(fileName)-5), ".vert", 5))
283          tmpType = SHADER;
284#endif /* NO_SHADERS */
285#ifndef NO_TEXTURES
286#ifdef __IF_OK
287        else
288#else
289  if
290#endif
291          tmpType = IMAGE;
292#endif /* NO_TEXTURES */
293#undef __IF_OK
294  return this->load(fileName, tmpType, prio, param0, param1, param2);
295}
296
297/**
298 * @brief caches a Resource
299 *
300 * @see load;
301 *
302 * @brief returns true if ok, false otherwise.
303 * This function loads a Resource without applying it to an Object.
304 * This is for loading purposes, e.g, when the user is loading a Resource
305 * during the initialisation instead of at Runtime.
306 */
307bool ResourceManager::cache(const char* fileName, ResourceType type, ResourcePriority prio,
308                            const MultiType& param0, const MultiType& param1, const MultiType& param2)
309{
310  assert(fileName != NULL);
311
312  // searching if the resource was loaded before.
313  Resource* tmpResource;
314  // check if we already loaded this Resource
315  tmpResource = this->locateResourceByInfo(fileName, type, param0, param1, param2);
316  // otherwise load it
317  if (tmpResource == NULL)
318    tmpResource = this->loadResource(fileName, type, prio, param0, param1, param2);
319  // return cached pointer.
320  if (tmpResource != NULL) // if the resource was loaded before.
321  {
322    if(tmpResource->prio < prio)
323      tmpResource->prio = prio;
324    return true;
325  }
326  else
327    return false;
328}
329
330/**
331 * tells the ResourceManager to generate a Copy of the Resource.
332 * @brief resourcePointer: The Pointer to the resource to copy
333 * @returns the Resource pointed to resourcePointer.
334 */
335BaseObject* ResourceManager::copy(BaseObject* resourcePointer)
336{
337  Resource* tmp = locateResourceByPointer(resourcePointer);
338  if (tmp!=NULL)
339  {
340    tmp->count++;
341    return tmp->pointer;
342  }
343  else
344    return NULL;
345}
346
347
348/**
349 * @brief loads resources
350 * @param fileName: The fileName of the resource to load
351 * @param type: The Type of Resource to load.
352 * @param prio: The ResourcePriority of this resource (will only be increased)
353 * @param param0: an additional option to parse (see the constuctors for more help)
354 * @param param1: an additional option to parse (see the constuctors for more help)
355 * @param param2: an additional option to parse (see the constuctors for more help)
356 * @returns a pointer to a desired Resource.
357*/
358BaseObject* ResourceManager::load(const char* fileName, ResourceType type, ResourcePriority prio,
359                                  const MultiType& param0, const MultiType& param1, const MultiType& param2)
360{
361  assert(fileName != NULL);
362
363  // searching if the resource was loaded before.
364  Resource* tmpResource;
365  // check if we already loaded this Resource
366  tmpResource = this->locateResourceByInfo(fileName, type, param0, param1, param2);
367  // otherwise load it
368  if (tmpResource == NULL)
369  {
370    tmpResource = this->loadResource(fileName, type, prio, param0, param1, param2);
371  }
372  // return cached pointer.
373  if (tmpResource != NULL) // if the resource was loaded before.
374  {
375    tmpResource->count++;
376    if(tmpResource->prio < prio)
377      tmpResource->prio = prio;
378
379    return tmpResource->pointer;
380  }
381  else
382    return NULL;
383}
384
385
386/**
387 * @brief loads resources for internal purposes
388 * @param fileName: The fileName of the resource to load
389 * @param type: The Type of Resource to load.
390 * @param prio: The ResourcePriority of this resource (will only be increased)
391 * @param param0: an additional option to parse (see the constuctors for more help)
392 * @param param1: an additional option to parse (see the constuctors for more help)
393 * @param param2: an additional option to parse (see the constuctors for more help)
394 * @returns a pointer to a desired Resource.
395 */
396Resource* ResourceManager::loadResource(const char* fileName, ResourceType type, ResourcePriority prio,
397                                        const MultiType& param0, const MultiType& param1, const MultiType& param2)
398{
399  // Setting up the new Resource
400  Resource* tmpResource = new Resource;
401  tmpResource->count = 0;
402  tmpResource->type = type;
403  tmpResource->prio = prio;
404  tmpResource->pointer = NULL;
405  tmpResource->name = new char[strlen(fileName)+1];
406  strcpy(tmpResource->name, fileName);
407
408  // creating the full name. (directoryName + FileName)
409  char* fullName = ResourceManager::getFullName(fileName);
410  // Checking for the type of resource \see ResourceType
411  switch(type)
412  {
413#ifndef NO_MODEL
414    case OBJ:
415      if (param0.getType() != MT_NULL)
416        tmpResource->param[0] = param0;
417      else
418        tmpResource->param[0] = 1.0f;
419
420      if(ResourceManager::isFile(fullName))
421        tmpResource->pointer = new OBJModel(fullName, tmpResource->param[0].getFloat());
422      else
423      {
424        PRINTF(2)("File %s in %s does not exist. Loading a cube-Model instead\n", fileName, dataDir);
425        tmpResource->pointer = ResourceManager::load("cube", PRIM, prio, tmpResource->param[0].getFloat());
426      }
427      break;
428    case PRIM:
429      if (param0 != MT_NULL)
430        tmpResource->param[0] = param0;
431      else
432        tmpResource->param[0] = 1.0f;
433
434      if (!strcmp(tmpResource->name, "cube"))
435        tmpResource->pointer = new PrimitiveModel(PRIM_CUBE, tmpResource->param[0].getFloat());
436      else if (!strcmp(tmpResource->name, "sphere"))
437        tmpResource->pointer = new PrimitiveModel(PRIM_SPHERE, tmpResource->param[0].getFloat());
438      else if (!strcmp(tmpResource->name, "plane"))
439        tmpResource->pointer = new PrimitiveModel(PRIM_PLANE, tmpResource->param[0].getFloat());
440      else if (!strcmp(tmpResource->name, "cylinder"))
441        tmpResource->pointer = new PrimitiveModel(PRIM_CYLINDER, tmpResource->param[0].getFloat());
442      else if (!strcmp(tmpResource->name, "cone"))
443        tmpResource->pointer = new PrimitiveModel(PRIM_CONE, tmpResource->param[0].getFloat());
444      break;
445    case MD2:
446      if(ResourceManager::isFile(fullName))
447      {
448        tmpResource->param[0] = param0;
449        tmpResource->param[1] = param1;
450        tmpResource->pointer = new MD2Data(fullName, tmpResource->param[0].getString(), tmpResource->param[1].getFloat());
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, tmpResource->param[0].getInt());
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      delete resource->pointer;
595      // deleting the List Entry:
596      PRINTF(4)("Resource %s safely removed.\n", resource->name);
597      delete[] resource->name;
598      std::vector<Resource*>::iterator resourceIT = std::find(this->resourceList.begin(), this->resourceList.end(), resource);
599      this->resourceList.erase(resourceIT);
600      delete resource;
601    }
602    else
603      PRINTF(4)("Resource %s not removed, because there are still %d References to it.\n", resource->name, resource->count);
604  }
605  else
606    PRINTF(4)("not deleting resource %s because DeleteLevel to high\n", resource->name);
607  return true;
608}
609
610
611/**
612 * @brief unloads all alocated Memory of Resources with a pririty lower than prio
613 * @param prio The priority to delete
614*/
615bool ResourceManager::unloadAllByPriority(ResourcePriority prio)
616{
617  unsigned int removeCount;
618  for (unsigned int round = 0; round < 3; round++)
619  {
620    int index = this->resourceList.size() - 1;
621    removeCount = 0;
622    while (index >= 0)
623    {
624      if (this->resourceList[index]->prio <= prio)
625      {
626        if (this->resourceList[index]->count == 0)
627          unload(this->resourceList[index], prio);
628        else
629        {
630          if (round == 3)
631            PRINTF(2)("unable to unload %s because there are still %d references to it\n",
632                      this->resourceList[index]->name, this->resourceList[index]->count);
633          removeCount++;
634        }
635      }
636      index--;
637    }
638    if (removeCount == 0) break;
639  }
640}
641
642
643/**
644 * @brief Searches for a Resource by some information
645 * @param fileName: The name to look for
646 * @param type the Type of resource to locate.
647 * @param param0: an additional option to parse (see the constuctors for more help)
648 * @param param1: an additional option to parse (see the constuctors for more help)
649 * @param param2: an additional option to parse (see the constuctors for more help)
650 * @returns a Pointer to the Resource if found, NULL otherwise.
651*/
652Resource* ResourceManager::locateResourceByInfo(const char* fileName, ResourceType type,
653    const MultiType& param0, const MultiType& param1, const MultiType& param2) const
654{
655  std::vector<Resource*>::const_iterator resource;
656  for (resource = this->resourceList.begin(); resource != this->resourceList.end(); resource++)
657  {
658    if ((*resource)->type == type && !strcmp(fileName, (*resource)->name))
659    {
660      bool match = false;
661      switch (type)
662      {
663#ifndef NO_MODEL
664        case PRIM:
665        case OBJ:
666          if (param0 == MT_NULL)
667          {
668            if ((*resource)->param[0] == 1.0f)
669              match = true;
670          }
671          else if ((*resource)->param[0] == param0.getFloat())
672            match = true;
673          break;
674        case MD2:
675          if (param0 == MT_NULL && ((*resource)->param[0] == "") && param1 == MT_NULL && ((*resource)->param[0] == 1.0f))
676              match = true;
677          else if ((*resource)->param[0] == ((MultiType)param0).getString() && (*resource)->param[1] == ((MultiType)param1).getFloat())
678            match = true;
679          break;
680#endif /* NO_MODEL */
681#ifndef NO_TEXT
682        case TTF:
683          if (param0 == MT_NULL)
684          {
685            if ((*resource)->param[0] == FONT_DEFAULT_RENDER_SIZE)
686              match = true;
687          }
688          else if ((*resource)->param[0] == param0.getInt())
689            match = true;
690          break;
691#endif /* NO_TEXT */
692#ifndef NO_SHADERS
693        case SHADER:
694          if (param0 == MT_NULL)
695          {
696            if ((*resource)->param[0] == "")
697              match = true;
698          }
699          else if ((*resource)->param[0] == ((MultiType)param0).getString())
700            match = true;
701          break;
702#endif /* NO_SHADERS */
703#ifndef NO_TEXTURES
704        case IMAGE:
705          if (param0 == MT_NULL)
706          {
707            if ((*resource)->param[0] == GL_TEXTURE_2D)
708              match = true;
709          }
710          else if ((*resource)->param[0] ==  param0.getInt())
711            match = true;
712          break;
713#endif /* NO_TEXTURES */
714        default:
715          match = true;
716          break;
717      }
718      if (match)
719      {
720        return (*resource);
721      }
722    }
723  }
724  return NULL;
725}
726
727/**
728 * @brief Searches for a Resource by Pointer
729 * @param pointer the Pointer to search for
730 * @returns a Pointer to the Resource if found, NULL otherwise.
731 */
732Resource* ResourceManager::locateResourceByPointer(const void* pointer) const
733{
734  //  Resource* enumRes = resourceList->enumerate();
735  std::vector<Resource*>::const_iterator resource;
736  for (resource = this->resourceList.begin(); resource != this->resourceList.end(); resource++)
737    if (pointer == (*resource)->pointer)
738      return (*resource);
739  return NULL;
740}
741
742char* ResourceManager::toResourcableString(unsigned int i)
743{
744  int len = strlen(ResourceManager::ResourceTypeToChar(this->resourceList[i]->type));
745  len += strlen(this->resourceList[i]->name);
746  if (this->resourceList[i]->param[0].getString()) len += strlen(this->resourceList[i]->param[0].getString()) +1;
747  if (this->resourceList[i]->param[1].getString()) len += strlen(this->resourceList[i]->param[1].getString()) +1;
748  if (this->resourceList[i]->param[2].getString()) len += strlen(this->resourceList[i]->param[2].getString()) +1;
749  len += 10;
750  char* tmp = new char[len];
751  tmp[0] = '\0';
752  strcat( tmp, ResourceManager::ResourceTypeToChar(this->resourceList[i]->type));
753  strcat(tmp,",");
754  strcat (tmp, this->resourceList[i]->name);
755  if (this->resourceList[i]->param[0].getString() && this->resourceList[i]->param[0].getString() != '\0')
756  {
757    strcat(tmp,",");
758    strcat( tmp, this->resourceList[i]->param[0].getString());
759  }
760  if (this->resourceList[i]->param[1].getString() && this->resourceList[i]->param[1].getString() != '\0')
761  {
762    strcat(tmp,",");
763    strcat( tmp, this->resourceList[i]->param[1].getString());
764  }
765  if (this->resourceList[i]->param[2].getString() && this->resourceList[i]->param[2].getString() != '\0')
766  {
767    strcat(tmp,",");
768    strcat( tmp, this->resourceList[i]->param[2].getString());
769  }
770  return tmp;
771}
772
773/**
774 * @brief caches a Resource from a ResourceableString created with the toResourcableString-function
775 * @param resourceableString the String to cache the resource from.
776 */
777bool ResourceManager::fromResourceableString(const char* resourceableString)
778{
779  SubString splits(resourceableString, ',');
780  splits.debug();
781  if (splits.getCount() == 2)
782    this->cache(splits[1], ResourceManager::stringToResourceType(splits[0]),
783                RP_LEVEL);
784  else if (splits.getCount() == 3)
785    return this->cache(splits[1], ResourceManager::stringToResourceType(splits[0]),
786                RP_LEVEL, splits[2]);
787  else if (splits.getCount() == 4)
788    return this->cache(splits[1], ResourceManager::stringToResourceType(splits[0]),
789                RP_LEVEL, splits[2], splits[3]);
790  else if (splits.getCount() == 5)
791    return this->cache(splits[1], ResourceManager::stringToResourceType(splits[0]),
792                RP_LEVEL, splits[2], splits[3], splits[4]);
793}
794
795
796/**
797 * @brief Checks if it is a Directory
798 * @param directoryName the Directory to check for
799 * @returns true if it is a directory/symlink false otherwise
800*/
801bool ResourceManager::isDir(const char* directoryName)
802{
803  if (directoryName == NULL)
804    return false;
805
806  char* tmpDirName = NULL;
807  struct stat status;
808
809  // checking for the termination of the string given. If there is a "/" at the end cut it away
810  if (directoryName[strlen(directoryName)-1] == '/' ||
811      directoryName[strlen(directoryName)-1] == '\\')
812  {
813    tmpDirName = new char[strlen(directoryName)];
814    strncpy(tmpDirName, directoryName, strlen(directoryName)-1);
815    tmpDirName[strlen(directoryName)-1] = '\0';
816  }
817  else
818  {
819    tmpDirName = new char[strlen(directoryName)+1];
820    strcpy(tmpDirName, directoryName);
821  }
822
823  if(!stat(tmpDirName, &status))
824  {
825    if (status.st_mode & (S_IFDIR
826#ifndef __WIN32__
827                          | S_IFLNK
828#endif
829                         ))
830    {
831      delete[] tmpDirName;
832      return true;
833    }
834    else
835    {
836      delete[] tmpDirName;
837      return false;
838    }
839  }
840  else
841  {
842    delete[] tmpDirName;
843    return false;
844  }
845}
846
847/**
848 * @brief Checks if the file is either a Regular file or a Symlink
849 * @param fileName the File to check for
850 * @returns true if it is a regular file/symlink, false otherwise
851*/
852bool ResourceManager::isFile(const char* fileName)
853{
854  if (fileName == NULL)
855    return false;
856  char* tmpFileName = ResourceManager::homeDirCheck(fileName);
857  // actually checks the File
858  struct stat status;
859  if (!stat(tmpFileName, &status))
860  {
861    if (status.st_mode & (S_IFREG
862#ifndef __WIN32__
863                          | S_IFLNK
864#endif
865                         ))
866    {
867      delete[] tmpFileName;
868      return true;
869    }
870    else
871    {
872      delete[] tmpFileName;
873      return false;
874    }
875  }
876  else
877  {
878    delete[] tmpFileName;
879    return false;
880  }
881}
882
883/**
884 * @brief touches a File on the disk (thereby creating it)
885 * @param fileName The file to touch
886*/
887bool ResourceManager::touchFile(const char* fileName)
888{
889  char* tmpName = ResourceManager::homeDirCheck(fileName);
890  if (tmpName == NULL)
891    return false;
892  FILE* stream;
893  if( (stream = fopen (tmpName, "w")) == NULL)
894  {
895    PRINTF(1)("could not open %s fro writing\n", fileName);
896    delete[] tmpName;
897    return false;
898  }
899  fclose(stream);
900
901  delete[] tmpName;
902}
903
904/**
905 * @brief deletes a File from disk
906 * @param fileName the File to delete
907*/
908bool ResourceManager::deleteFile(const char* fileName)
909{
910  if (fileName == NULL)
911    return false;
912  char* tmpName = ResourceManager::homeDirCheck(fileName);
913  unlink(tmpName);
914  delete[] tmpName;
915}
916
917/**
918 * @param name the Name of the file to check
919 * @returns The name of the file, including the HomeDir
920 * IMPORTANT: this has to be deleted from the outside
921 */
922char* ResourceManager::homeDirCheck(const char* name)
923{
924  if (name == NULL)
925    return NULL;
926  char* retName;
927  if (!strncmp(name, "~/", 2))
928  {
929    char tmpFileName[500];
930#ifdef __WIN32__
931    strcpy(tmpFileName, getenv("USERPROFILE"));
932#else
933    strcpy(tmpFileName, getenv("HOME"));
934#endif
935    retName = new char[strlen(tmpFileName)+strlen(name)];
936    sprintf(retName, "%s%s", tmpFileName, name+1);
937  }
938  else
939  {
940    retName = new char[strlen(name)+1];
941    strcpy(retName, name);
942  }
943  return retName;
944}
945
946/**
947 * @param fileName the Name of the File to check
948 * @returns The full name of the file, including the DataDir, and NULL if the file does not exist
949 * !!IMPORTANT: this has to be deleted from the outside!!
950*/
951char* ResourceManager::getFullName(const char* fileName)
952{
953  if (fileName == NULL || ResourceManager::getInstance()->getDataDir() == NULL)
954    return NULL;
955
956  char* retName = new char[strlen(ResourceManager::getInstance()->getDataDir())
957                           + strlen(fileName) + 1];
958  sprintf(retName, "%s%s", ResourceManager::getInstance()->getDataDir(), fileName);
959  if (ResourceManager::isFile(retName) || ResourceManager::isDir(retName))
960    return retName;
961  else
962  {
963    delete[] retName;
964    return NULL;
965  }
966}
967
968
969/**
970 * @brief checks wether a file is in the DataDir.
971 * @param fileName the File to check if it is in the Data-Dir structure.
972 * @returns true if the file exists, false otherwise
973 */
974bool ResourceManager::isInDataDir(const char* fileName)
975{
976  if (fileName == NULL || ResourceManager::getInstance()->getDataDir() == NULL)
977    return false;
978
979  bool retVal = false;
980  char* checkFile = new char[strlen(ResourceManager::getInstance()->getDataDir())
981                             + strlen(fileName) + 1];
982  sprintf(checkFile, "%s%s", ResourceManager::getInstance()->getDataDir(), fileName);
983
984  if (ResourceManager::isFile(checkFile) || ResourceManager::isDir(checkFile))
985    retVal = true;
986  else
987    retVal = false;
988  delete[] checkFile;
989  return retVal;
990}
991
992
993/**
994 * @brief outputs debug information about the ResourceManager
995 */
996void ResourceManager::debug() const
997{
998  PRINT(0)("=RM===================================\n");
999  PRINT(0)("= RESOURCE-MANAGER DEBUG INFORMATION =\n");
1000  PRINT(0)("======================================\n");
1001  // if it is not initialized
1002  PRINT(0)(" Reference is: %p\n", ResourceManager::singletonRef);
1003  PRINT(0)(" Data-Directory is: %s\n", this->dataDir);
1004  PRINT(0)(" List of Image-Directories: ");
1005  std::vector<char*>::const_iterator imageDir;
1006  for (imageDir = this->imageDirs.begin(); imageDir != this->imageDirs.end(); imageDir++)
1007    PRINT(0)("%s ", (*imageDir));
1008  PRINT(0)("\n");
1009
1010  PRINT(0)("List of all stored Resources:\n");
1011  std::vector<Resource*>::const_iterator resource;
1012  for (resource = this->resourceList.begin(); resource != this->resourceList.end(); resource++)
1013
1014  {
1015    PRINT(0)("-----------------------------------------\n");
1016    PRINT(0)("Name: %s; References: %d; Type: %s ", (*resource)->name, (*resource)->count, ResourceManager::ResourceTypeToChar((*resource)->type));
1017
1018    PRINT(0)("gets deleted at ");
1019    switch((*resource)->prio)
1020    {
1021      default:
1022      case RP_NO:
1023        PRINT(0)("first posibility (0)\n");
1024        break;
1025      case RP_LEVEL:
1026        PRINT(0)("the end of the Level (1)\n");
1027        break;
1028      case RP_CAMPAIGN:
1029        PRINT(0)("the end of the campaign (2)\n");
1030        break;
1031      case RP_GAME:
1032        PRINT(0)("when leaving the game (3)\n");
1033        break;
1034    }
1035  }
1036
1037
1038
1039  PRINT(0)("==================================RM==\n");
1040}
1041
1042
1043/**
1044 * @brief converts a ResourceType into the corresponding String
1045 * @param type the ResourceType to translate
1046 * @returns the converted String.
1047 */
1048const char* ResourceManager::ResourceTypeToChar(ResourceType type)
1049{
1050  return ResourceManager::resourceNames[type];
1051}
1052
1053/**
1054 * @brief converts a String into a ResourceType (good for loading)
1055 * @param resourceType the name of the Type
1056 * @returns the Number of the Type, or 0 (defautl) if not found.
1057 */
1058ResourceType ResourceManager::stringToResourceType(const char* resourceType)
1059{
1060  assert(resourceType != NULL);
1061  for (unsigned int i = 0; i < RESOURCE_TYPE_SIZE; i++)
1062    if (!strcmp(resourceType, ResourceManager::resourceNames[i]))
1063      return (ResourceType)i;
1064  return (ResourceType)0;
1065}
1066
1067/**
1068 * The Names of the ResourceTypes
1069 */
1070const char* ResourceManager::resourceNames[] =
1071  {
1072#ifndef NO_MODEL
1073    "ObjectModel",
1074    "PrimitiveModel",
1075    "MD2-Data",
1076#endif
1077#ifndef NO_TEXT
1078    "Font",
1079#endif
1080#ifndef NO_AUDIO
1081    "Wav",
1082    "mp3",
1083    "ogg",
1084#endif
1085#ifndef NO_TEXTURES
1086    "Texture",
1087#endif
1088#ifndef NO_SHADERS
1089    "Shader",
1090#endif
1091
1092  };
Note: See TracBrowser for help on using the repository browser.