Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 7171 was 7059, checked in by bensch, 19 years ago

md2 model resource managed

File size: 32.1 KB
RevLine 
[4597]1/*
[1853]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.
[1855]10
11   ### File Specific:
[3655]12   main-programmer: Benjamin Grauer
[3672]13   co-programmer: Patrick Boenzli
[1853]14*/
15
[3655]16#define DEBUG_SPECIAL_MODULE DEBUG_MODULE_LOAD
[1853]17
[3655]18#include "resource_manager.h"
[1853]19
[6648]20#include "substring.h"
[4642]21#include "debug.h"
22
[6222]23#include <algorithm>
[6655]24#include <assert.h>
[6222]25
[3655]26// different resource Types
[4534]27#ifndef NO_MODEL
[3655]28#include "objModel.h"
[3657]29#include "primitive_model.h"
[4462]30#include "md2Model.h"
[4534]31#endif /* NO_MODEL */
32#ifndef NO_TEXTURES
[3655]33#include "texture.h"
[4534]34#endif /* NO_TEXTURES */
35#ifndef NO_TEXT
[5344]36#include "font.h"
[4534]37#endif /* NO_TEXT */
38#ifndef NO_AUDIO
[5930]39#include "sound_buffer.h"
[4961]40#include "ogg_player.h"
[4534]41#endif /* NO_AUDIO */
[5323]42#ifndef NO_SHADERS
43#include "shader.h"
44#endif /* NO_SHADERS */
[1853]45
[3655]46// File Handling Includes
47#include <sys/types.h>
48#include <sys/stat.h>
49#include <unistd.h>
50
[1856]51using namespace std;
[1853]52
[3245]53/**
[6647]54 * @brief standard constructor
[3245]55*/
[4597]56ResourceManager::ResourceManager ()
[3365]57{
[4597]58  this->setClassID(CL_RESOURCE_MANAGER, "ResourceManager");
59  this->setName("ResourceManager");
60
[5423]61  this->dataDir = new char[3];
62  strcpy(this->dataDir, "./");
[5480]63  this->tryDataDir("./data");
[3365]64}
[1853]65
[3658]66//! Singleton Reference to the ResourceManager
[3655]67ResourceManager* ResourceManager::singletonRef = NULL;
68
[3245]69/**
[6647]70 * @brief standard destructor
[3655]71*/
[4746]72ResourceManager::~ResourceManager ()
[3655]73{
[3660]74  // deleting the Resources-List
[3672]75  this->unloadAllByPriority(RP_GAME);
[5303]76
[6222]77  if (!this->resourceList.empty())
78    PRINTF(1)("Not removed all Resources, since there are still %d resources registered\n", this->resourceList.size());
[5303]79
[3660]80  // deleting the Directorie Lists
[6222]81  while (!this->imageDirs.empty())
[6640]82  {
[6642]83    delete[] this->imageDirs.back();
84    this->imageDirs.pop_back();
[6640]85  }
[3672]86
[5211]87  delete[] this->dataDir;
88
[3655]89  ResourceManager::singletonRef = NULL;
90}
[1853]91
[3655]92/**
[6647]93 * @brief sets the data main directory
[4836]94 * @param dataDir the DataDirectory.
[5480]95 */
[3883]96bool ResourceManager::setDataDir(const char* dataDir)
[3543]97{
[4341]98  char* realDir = ResourceManager::homeDirCheck(dataDir);
99  if (isDir(realDir))
[5480]100  {
101    delete[] this->dataDir;
102    if (dataDir[strlen(dataDir)-1] == '/' || dataDir[strlen(dataDir)-1] == '\\')
[3655]103    {
[5480]104      this->dataDir = new char[strlen(realDir)+1];
105      strcpy(this->dataDir, realDir);
[3655]106    }
[5480]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  }
[3655]117  else
[5480]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/**
[6647]126 * @brief sets the data main directory
[5480]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] == '\\')
[3655]138    {
[5480]139      this->dataDir = new char[strlen(realDir)+1];
140      strcpy(this->dataDir, realDir);
[3655]141    }
[5480]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  }
[5483]152  delete[] realDir;
[5482]153  return false;
[3543]154}
[1853]155
[5480]156
[3660]157/**
[6647]158 * @brief checks for the DataDirectory, by looking if
[5480]159 * @param fileInside is iniside of the given directory.
[4091]160*/
[5480]161bool ResourceManager::verifyDataDir(const char* fileInside)
[4091]162{
163  bool retVal;
164  if (!isDir(this->dataDir))
[6640]165  {
166    PRINTF(1)("%s is not a directory\n", this->dataDir);
167    return false;
168  }
[4597]169
[4091]170  char* testFile = new char[strlen(this->dataDir)+strlen(fileInside)+1];
171  sprintf(testFile, "%s%s", this->dataDir, fileInside);
172  retVal = isFile(testFile);
[5208]173  delete[] testFile;
[4091]174  return retVal;
175}
176
[4653]177#ifndef NO_TEXTURES
[4091]178/**
[6647]179 * @brief adds a new Path for Images
[4836]180 * @param imageDir The path to insert
181 * @returns true, if the Path was well and injected (or already existent within the list)
[3660]182   false otherwise
183*/
[4370]184bool ResourceManager::addImageDir(const char* imageDir)
[3658]185{
[5335]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  }
[3660]202  // check if the param is a Directory
[5335]203  if (isDir(newDir))
[6640]204  {
205    // check if the Directory has been added before
[6642]206    std::vector<char*>::const_iterator imageDir;
[6640]207    for (imageDir = this->imageDirs.begin(); imageDir != this->imageDirs.end(); imageDir++)
[3658]208    {
[6640]209      if (!strcmp(*imageDir, newDir))
[6222]210      {
[6640]211        PRINTF(3)("Path %s already loaded\n", newDir);
212        delete[] newDir;
213        return true;
[6222]214      }
[3658]215    }
[6640]216    // adding the directory to the List
217    this->imageDirs.push_back(newDir);
218    return true;
219  }
[3658]220  else
[6640]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  }
[3658]226}
[4534]227#endif /* NO_TEXTURES */
[3658]228
[3245]229/**
[6647]230 * @brief loads resources
[4836]231 * @param fileName: The fileName of the resource to load
232 * @param prio: The ResourcePriority of this resource (will only be increased)
[6645]233 * @param param0: an additional option to parse (see the constuctors for more help)
[4836]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.
[3655]237*/
[6645]238BaseObject* ResourceManager::load(const char* fileName, ResourcePriority prio,
[6648]239                                  const MultiType& param0, const MultiType& param1, const MultiType& param2)
[3655]240{
[5366]241  if (fileName == NULL)
242    return NULL;
[3655]243  ResourceType tmpType;
[4534]244#ifndef NO_MODEL
[4637]245#define __IF_OK
[5323]246  if (!strncasecmp(fileName+(strlen(fileName)-4), ".obj", 4))
[3655]247    tmpType = OBJ;
[4534]248  else if (!strncmp(fileName+(strlen(fileName)-4), ".md2", 4))
[4462]249    tmpType = MD2;
[5323]250  else if (!strcasecmp(fileName, "cube") ||
251           !strcasecmp(fileName, "sphere") ||
252           !strcasecmp(fileName, "plane") ||
253           !strcasecmp(fileName, "cylinder") ||
254           !strcasecmp(fileName, "cone"))
[4534]255    tmpType = PRIM;
256#endif /* NO_MODEL */
257#ifndef NO_AUDIO
[4637]258#ifdef __IF_OK
259  else
260#endif
261#define __IF_OK
[6640]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;
[4534]268#endif /* NO_AUDIO */
269#ifndef NO_TEXT
[4637]270#ifdef __IF_OK
[6640]271    else
[4637]272#endif
273#define __IF_OK
[6640]274      if (!strncasecmp(fileName+(strlen(fileName)-4), ".ttf", 4))
275        tmpType = TTF;
[4534]276#endif /* NO_TEXT */
[5323]277#ifndef NO_SHADERS
278#ifdef __IF_OK
[6640]279      else
[5323]280#endif
281#define __IF_OK
[6640]282        if (!strncasecmp(fileName+(strlen(fileName)-5), ".vert", 5))
283          tmpType = SHADER;
[5323]284#endif /* NO_SHADERS */
[4534]285#ifndef NO_TEXTURES
[4637]286#ifdef __IF_OK
[6640]287        else
[4637]288#else
289  if
290#endif
[6640]291          tmpType = IMAGE;
[4534]292#endif /* NO_TEXTURES */
[4653]293#undef __IF_OK
[6645]294  return this->load(fileName, tmpType, prio, param0, param1, param2);
[3655]295}
296
297/**
[6647]298 * @brief caches a Resource
[6641]299 *
300 * @see load;
301 *
[6650]302 * @brief returns true if ok, false otherwise.
[6641]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 */
[6650]307bool ResourceManager::cache(const char* fileName, ResourceType type, ResourcePriority prio,
[6645]308                            const MultiType& param0, const MultiType& param1, const MultiType& param2)
[6641]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
[6645]315  tmpResource = this->locateResourceByInfo(fileName, type, param0, param1, param2);
[6641]316  // otherwise load it
317  if (tmpResource == NULL)
[6645]318    tmpResource = this->loadResource(fileName, type, prio, param0, param1, param2);
[6641]319  // return cached pointer.
320  if (tmpResource != NULL) // if the resource was loaded before.
[6650]321  {
[6641]322    if(tmpResource->prio < prio)
323      tmpResource->prio = prio;
[6650]324    return true;
325  }
326  else
327    return false;
[6641]328}
329
[6651]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}
[6641]346
[6651]347
[6641]348/**
[6647]349 * @brief loads resources
[4836]350 * @param fileName: The fileName of the resource to load
[5306]351 * @param type: The Type of Resource to load.
[4836]352 * @param prio: The ResourcePriority of this resource (will only be increased)
[6645]353 * @param param0: an additional option to parse (see the constuctors for more help)
[4836]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.
[3245]357*/
[5304]358BaseObject* ResourceManager::load(const char* fileName, ResourceType type, ResourcePriority prio,
[6645]359                                  const MultiType& param0, const MultiType& param1, const MultiType& param2)
[3655]360{
[6640]361  assert(fileName != NULL);
[5366]362
[3658]363  // searching if the resource was loaded before.
[6640]364  Resource* tmpResource;
365  // check if we already loaded this Resource
[6645]366  tmpResource = this->locateResourceByInfo(fileName, type, param0, param1, param2);
[6640]367  // otherwise load it
368  if (tmpResource == NULL)
[6648]369  {
[6645]370    tmpResource = this->loadResource(fileName, type, prio, param0, param1, param2);
[6648]371  }
[6640]372  // return cached pointer.
[5306]373  if (tmpResource != NULL) // if the resource was loaded before.
[6640]374  {
375    tmpResource->count++;
376    if(tmpResource->prio < prio)
377      tmpResource->prio = prio;
[6648]378
[6640]379    return tmpResource->pointer;
380  }
[3677]381  else
[6640]382    return NULL;
383}
[3658]384
[6640]385
386/**
[6647]387 * @brief loads resources for internal purposes
[6640]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)
[6645]391 * @param param0: an additional option to parse (see the constuctors for more help)
[6640]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,
[6645]397                                        const MultiType& param0, const MultiType& param1, const MultiType& param2)
[6640]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  {
[4534]413#ifndef NO_MODEL
[6648]414    case OBJ:
415      if (param0.getType() != MT_NULL)
416        tmpResource->param[0] = param0;
417      else
418        tmpResource->param[0] = 1.0f;
[3790]419
[6648]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;
[3790]433
[6648]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;
[7059]449        tmpResource->param[1] = param1;
450        tmpResource->pointer = new MD2Data(fullName, tmpResource->param[0].getString(), tmpResource->param[1].getFloat());
[6648]451      }
452      break;
[4534]453#endif /* NO_MODEL */
454#ifndef NO_TEXT
[6648]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;
[4597]463
[6648]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;
[4534]469#endif /* NO_TEXT */
470#ifndef NO_AUDIO
[6648]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;
[4534]479#endif /* NO_AUDIO */
480#ifndef NO_TEXTURES
[6648]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))
[6640]487      {
[6648]488        PRINTF(4)("Image %s resides to %s\n", fileName, fullName);
[6859]489        tmpResource->pointer = new Texture(fullName, tmpResource->param[0].getInt());
[6648]490      }
491      else
492      {
493        std::vector<char*>::iterator imageDir;
494        for (imageDir = this->imageDirs.begin(); imageDir != this->imageDirs.end(); imageDir++)
[6640]495        {
[6648]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          }
[6640]505          delete[] imgName;
506        }
507      }
[6648]508      if(!tmpResource)
509        PRINTF(2)("!!Image %s not Found!!\n", fileName);
510      break;
[4534]511#endif /* NO_TEXTURES */
[5323]512#ifndef NO_SHADERS
[6648]513    case SHADER:
514      if(ResourceManager::isFile(fullName))
[6640]515      {
[6648]516        if (param0 != MT_NULL)
[6640]517        {
[6648]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;
[4597]526        }
[6648]527        else
528        {
529          tmpResource->param[0] = param0;
530          tmpResource->pointer = new Shader(fullName, NULL);
531        }
[6640]532      }
[6648]533      break;
[6640]534#endif /* NO_SHADERS */
[6648]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;
[6640]539  }
[5216]540  if (tmpResource->pointer != NULL)
[6640]541    this->resourceList.push_back(tmpResource);
542  delete[] fullName;
543
544
545  if (tmpResource->pointer != NULL)
546    return tmpResource;
[4597]547  else
[6640]548  {
549    PRINTF(2)("Resource %s could not be loaded\n", fileName);
550    delete[] tmpResource->name;
551    delete tmpResource;
552    return NULL;
553  }
[3658]554}
555
556/**
[6647]557 * @brief unloads a Resource
[4836]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
[3658]561*/
[6651]562bool ResourceManager::unload(BaseObject* pointer, ResourcePriority prio)
[3658]563{
[5366]564  if (pointer == NULL)
565    return false;
[3658]566  // if pointer is existent. and only one resource of this type exists.
[3672]567  Resource* tmpResource = this->locateResourceByPointer(pointer);
[5366]568  if (tmpResource != NULL)
569    return unload(tmpResource, prio);
[3660]570  else
[5366]571  {
572    PRINTF(2)("Resource not Found %p\n", pointer);
573    return false;
574  }
[3660]575}
576
[4465]577/**
[6647]578 * @brief unloads a Resource
[4836]579 * @param resource: The resource to unloade
580 * @param prio the PriorityLevel to unload this resource
[5308]581 * @returns true on success, false otherwise.
[4465]582*/
[3660]583bool ResourceManager::unload(Resource* resource, ResourcePriority prio)
584{
[5306]585  if (resource == NULL)
586    return false;
[3665]587  if (resource->count > 0)
588    resource->count--;
[5306]589
[3660]590  if (resource->prio <= prio)
[6640]591  {
592    if (resource->count == 0)
[3658]593    {
[6640]594      // deleting the Resource
595      switch(resource->type)
596      {
[4534]597#ifndef NO_MODEL
[6648]598        case OBJ:
599        case PRIM:
600          delete (Model*)resource->pointer;
601          break;
602        case MD2:
603          delete (MD2Data*)resource->pointer;
604          break;
[4534]605#endif /* NO_MODEL */
606#ifndef NO_AUDIO
[6648]607        case WAV:
608          delete (SoundBuffer*)resource->pointer;
609          break;
610        case OGG:
611          delete (OggPlayer*)resource->pointer;
612          break;
[4534]613#endif /* NO_AUDIO */
614#ifndef NO_TEXT
[6648]615        case TTF:
616          delete (Font*)resource->pointer;
617          break;
[4534]618#endif /* NO_TEXT */
619#ifndef NO_TEXTURES
[6648]620        case IMAGE:
621          delete (Texture*)resource->pointer;
622          break;
[4534]623#endif /* NO_TEXTURES */
[5323]624#ifndef NO_SHADERS
[6648]625        case SHADER:
626          delete (Shader*)resource->pointer;
627          break;
[5323]628#endif /* NO_SHADERS */
[6648]629        default:
630          PRINTF(2)("NOT YET IMPLEMENTED !!FIX FIX!!\n");
631          return false;
632          break;
[6640]633      }
634      // deleting the List Entry:
635      PRINTF(4)("Resource %s safely removed.\n", resource->name);
636      delete[] resource->name;
[6642]637      std::vector<Resource*>::iterator resourceIT = std::find(this->resourceList.begin(), this->resourceList.end(), resource);
[6640]638      this->resourceList.erase(resourceIT);
639      delete resource;
[3658]640    }
[6640]641    else
642      PRINTF(4)("Resource %s not removed, because there are still %d References to it.\n", resource->name, resource->count);
643  }
[3658]644  else
[3660]645    PRINTF(4)("not deleting resource %s because DeleteLevel to high\n", resource->name);
[3658]646  return true;
[3655]647}
648
[3660]649
[3655]650/**
[6647]651 * @brief unloads all alocated Memory of Resources with a pririty lower than prio
[4836]652 * @param prio The priority to delete
[3660]653*/
654bool ResourceManager::unloadAllByPriority(ResourcePriority prio)
655{
[6222]656  unsigned int removeCount;
657  for (unsigned int round = 0; round < 3; round++)
658  {
[6642]659    int index = this->resourceList.size() - 1;
[6222]660    removeCount = 0;
[6642]661    while (index >= 0)
[3660]662    {
[6642]663      if (this->resourceList[index]->prio <= prio)
[6640]664      {
[6642]665        if (this->resourceList[index]->count == 0)
666          unload(this->resourceList[index], prio);
[6640]667        else
[6222]668        {
[6664]669          if (round == 3)
670            PRINTF(2)("unable to unload %s because there are still %d references to it\n",
671                      this->resourceList[index]->name, this->resourceList[index]->count);
[6640]672          removeCount++;
[6222]673        }
[6640]674      }
[6642]675      index--;
[6640]676    }
677    if (removeCount == 0) break;
[6222]678  }
[3660]679}
680
[5994]681
[3660]682/**
[6647]683 * @brief Searches for a Resource by some information
[4836]684 * @param fileName: The name to look for
685 * @param type the Type of resource to locate.
[6645]686 * @param param0: an additional option to parse (see the constuctors for more help)
[4836]687 * @param param1: an additional option to parse (see the constuctors for more help)
688 * @param param2: an additional option to parse (see the constuctors for more help)
689 * @returns a Pointer to the Resource if found, NULL otherwise.
[3658]690*/
[4462]691Resource* ResourceManager::locateResourceByInfo(const char* fileName, ResourceType type,
[6648]692    const MultiType& param0, const MultiType& param1, const MultiType& param2) const
[3658]693{
[6642]694  std::vector<Resource*>::const_iterator resource;
[6222]695  for (resource = this->resourceList.begin(); resource != this->resourceList.end(); resource++)
696  {
697    if ((*resource)->type == type && !strcmp(fileName, (*resource)->name))
[6640]698    {
699      bool match = false;
700      switch (type)
701      {
[4534]702#ifndef NO_MODEL
[6648]703        case PRIM:
704        case OBJ:
705          if (param0 == MT_NULL)
706          {
707            if ((*resource)->param[0] == 1.0f)
708              match = true;
709          }
710          else if ((*resource)->param[0] == param0.getFloat())
[6640]711            match = true;
[6648]712          break;
713        case MD2:
[7059]714          if (param0 == MT_NULL && ((*resource)->param[0] == "") && param1 == MT_NULL && ((*resource)->param[0] == 1.0f))
[6648]715              match = true;
[7059]716          else if ((*resource)->param[0] == ((MultiType)param0).getString() && (*resource)->param[1] == ((MultiType)param1).getFloat())
[6640]717            match = true;
[6648]718          break;
[4534]719#endif /* NO_MODEL */
720#ifndef NO_TEXT
[6648]721        case TTF:
722          if (param0 == MT_NULL)
723          {
724            if ((*resource)->param[0] == FONT_DEFAULT_RENDER_SIZE)
725              match = true;
726          }
727          else if ((*resource)->param[0] == param0.getInt())
[6640]728            match = true;
[6648]729          break;
[4534]730#endif /* NO_TEXT */
[5323]731#ifndef NO_SHADERS
[6648]732        case SHADER:
733          if (param0 == MT_NULL)
734          {
735            if ((*resource)->param[0] == "")
736              match = true;
737          }
738          else if ((*resource)->param[0] == ((MultiType)param0).getString())
[6640]739            match = true;
[6859]740          break;
[5323]741#endif /* NO_SHADERS */
[6467]742#ifndef NO_TEXTURES
[6648]743        case IMAGE:
744          if (param0 == MT_NULL)
745          {
746            if ((*resource)->param[0] == GL_TEXTURE_2D)
747              match = true;
748          }
749          else if ((*resource)->param[0] ==  param0.getInt())
[6640]750            match = true;
[6859]751          break;
[6648]752#endif /* NO_TEXTURES */
753        default:
[6640]754          match = true;
[6648]755          break;
[6640]756      }
757      if (match)
758      {
759        return (*resource);
760      }
[3658]761    }
[6640]762  }
[3658]763  return NULL;
764}
765
766/**
[6647]767 * @brief Searches for a Resource by Pointer
[4836]768 * @param pointer the Pointer to search for
769 * @returns a Pointer to the Resource if found, NULL otherwise.
[6647]770 */
[5994]771Resource* ResourceManager::locateResourceByPointer(const void* pointer) const
[3658]772{
[3667]773  //  Resource* enumRes = resourceList->enumerate();
[6642]774  std::vector<Resource*>::const_iterator resource;
[6222]775  for (resource = this->resourceList.begin(); resource != this->resourceList.end(); resource++)
776    if (pointer == (*resource)->pointer)
[6640]777      return (*resource);
[3658]778  return NULL;
779}
780
[6648]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
[3658]812/**
[6648]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)
[6650]824    return this->cache(splits[1], ResourceManager::stringToResourceType(splits[0]),
[6648]825                RP_LEVEL, splits[2]);
826  else if (splits.getCount() == 4)
[6650]827    return this->cache(splits[1], ResourceManager::stringToResourceType(splits[0]),
[6648]828                RP_LEVEL, splits[2], splits[3]);
829  else if (splits.getCount() == 5)
[6650]830    return this->cache(splits[1], ResourceManager::stringToResourceType(splits[0]),
[6648]831                RP_LEVEL, splits[2], splits[3], splits[4]);
832}
833
834
835/**
[6647]836 * @brief Checks if it is a Directory
[4836]837 * @param directoryName the Directory to check for
838 * @returns true if it is a directory/symlink false otherwise
[3655]839*/
840bool ResourceManager::isDir(const char* directoryName)
841{
[4462]842  if (directoryName == NULL)
843    return false;
844
[3883]845  char* tmpDirName = NULL;
[3655]846  struct stat status;
[3883]847
848  // checking for the termination of the string given. If there is a "/" at the end cut it away
[5113]849  if (directoryName[strlen(directoryName)-1] == '/' ||
850      directoryName[strlen(directoryName)-1] == '\\')
[6640]851  {
852    tmpDirName = new char[strlen(directoryName)];
853    strncpy(tmpDirName, directoryName, strlen(directoryName)-1);
854    tmpDirName[strlen(directoryName)-1] = '\0';
855  }
[3883]856  else
[6640]857  {
858    tmpDirName = new char[strlen(directoryName)+1];
859    strcpy(tmpDirName, directoryName);
860  }
[3883]861
[4032]862  if(!stat(tmpDirName, &status))
[6640]863  {
864    if (status.st_mode & (S_IFDIR
[3790]865#ifndef __WIN32__
[6640]866                          | S_IFLNK
[3790]867#endif
[6640]868                         ))
869    {
870      delete[] tmpDirName;
871      return true;
[3883]872    }
[6640]873    else
874    {
875      delete[] tmpDirName;
876      return false;
877    }
878  }
[3658]879  else
[5211]880  {
881    delete[] tmpDirName;
[4032]882    return false;
[5211]883  }
[3655]884}
885
886/**
[6647]887 * @brief Checks if the file is either a Regular file or a Symlink
[4836]888 * @param fileName the File to check for
889 * @returns true if it is a regular file/symlink, false otherwise
[3655]890*/
891bool ResourceManager::isFile(const char* fileName)
892{
[4462]893  if (fileName == NULL)
894    return false;
[4032]895  char* tmpFileName = ResourceManager::homeDirCheck(fileName);
896  // actually checks the File
[3655]897  struct stat status;
[4032]898  if (!stat(tmpFileName, &status))
[6640]899  {
900    if (status.st_mode & (S_IFREG
[3790]901#ifndef __WIN32__
[6640]902                          | S_IFLNK
[3790]903#endif
[6640]904                         ))
905    {
906      delete[] tmpFileName;
907      return true;
[4032]908    }
[6640]909    else
[4032]910    {
[5208]911      delete[] tmpFileName;
[4032]912      return false;
913    }
[6640]914  }
915  else
916  {
917    delete[] tmpFileName;
918    return false;
919  }
[4032]920}
921
[4166]922/**
[6647]923 * @brief touches a File on the disk (thereby creating it)
[4836]924 * @param fileName The file to touch
[4166]925*/
[4032]926bool ResourceManager::touchFile(const char* fileName)
927{
928  char* tmpName = ResourceManager::homeDirCheck(fileName);
[4462]929  if (tmpName == NULL)
930    return false;
[4032]931  FILE* stream;
932  if( (stream = fopen (tmpName, "w")) == NULL)
[6640]933  {
934    PRINTF(1)("could not open %s fro writing\n", fileName);
935    delete[] tmpName;
936    return false;
937  }
[4033]938  fclose(stream);
[4597]939
[5208]940  delete[] tmpName;
[4032]941}
942
[4166]943/**
[6647]944 * @brief deletes a File from disk
[4836]945 * @param fileName the File to delete
[4166]946*/
[4032]947bool ResourceManager::deleteFile(const char* fileName)
948{
[4462]949  if (fileName == NULL)
950    return false;
[4032]951  char* tmpName = ResourceManager::homeDirCheck(fileName);
952  unlink(tmpName);
[5208]953  delete[] tmpName;
[4032]954}
955
[4597]956/**
[4961]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 */
[4032]961char* ResourceManager::homeDirCheck(const char* name)
962{
[4462]963  if (name == NULL)
964    return NULL;
[4032]965  char* retName;
966  if (!strncmp(name, "~/", 2))
[6640]967  {
968    char tmpFileName[500];
[4032]969#ifdef __WIN32__
[6640]970    strcpy(tmpFileName, getenv("USERPROFILE"));
[4032]971#else
[6640]972    strcpy(tmpFileName, getenv("HOME"));
[4032]973#endif
[6640]974    retName = new char[strlen(tmpFileName)+strlen(name)];
975    sprintf(retName, "%s%s", tmpFileName, name+1);
976  }
[3655]977  else
[6640]978  {
979    retName = new char[strlen(name)+1];
980    strcpy(retName, name);
981  }
[4032]982  return retName;
[3655]983}
[3676]984
[4597]985/**
[4961]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
[5219]988 * !!IMPORTANT: this has to be deleted from the outside!!
[4166]989*/
990char* ResourceManager::getFullName(const char* fileName)
991{
[5335]992  if (fileName == NULL || ResourceManager::getInstance()->getDataDir() == NULL)
[4462]993    return NULL;
994
[4216]995  char* retName = new char[strlen(ResourceManager::getInstance()->getDataDir())
[4597]996                           + strlen(fileName) + 1];
[4166]997  sprintf(retName, "%s%s", ResourceManager::getInstance()->getDataDir(), fileName);
[4462]998  if (ResourceManager::isFile(retName) || ResourceManager::isDir(retName))
[4167]999    return retName;
1000  else
[6640]1001  {
1002    delete[] retName;
1003    return NULL;
1004  }
[4166]1005}
[4032]1006
1007
[3676]1008/**
[6647]1009 * @brief checks wether a file is in the DataDir.
[5335]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())
[6640]1020                             + strlen(fileName) + 1];
[5335]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/**
[6647]1033 * @brief outputs debug information about the ResourceManager
1034 */
[4746]1035void ResourceManager::debug() const
[3676]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: ");
[6642]1044  std::vector<char*>::const_iterator imageDir;
[6222]1045  for (imageDir = this->imageDirs.begin(); imageDir != this->imageDirs.end(); imageDir++)
[6640]1046    PRINT(0)("%s ", (*imageDir));
[3676]1047  PRINT(0)("\n");
1048
1049  PRINT(0)("List of all stored Resources:\n");
[6642]1050  std::vector<Resource*>::const_iterator resource;
[6222]1051  for (resource = this->resourceList.begin(); resource != this->resourceList.end(); resource++)
1052
[6640]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)
[3676]1059    {
[6648]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;
[3676]1073    }
[6640]1074  }
[3676]1075
1076
1077
1078  PRINT(0)("==================================RM==\n");
1079}
[5306]1080
1081
1082/**
[6647]1083 * @brief converts a ResourceType into the corresponding String
[5306]1084 * @param type the ResourceType to translate
1085 * @returns the converted String.
1086 */
1087const char* ResourceManager::ResourceTypeToChar(ResourceType type)
1088{
[6646]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[] =
[6648]1110  {
[5306]1111#ifndef NO_MODEL
[6648]1112    "ObjectModel",
1113    "PrimitiveModel",
1114    "MD2-Data",
[5306]1115#endif
[6648]1116#ifndef NO_TEXT
1117    "Font",
[5306]1118#endif
1119#ifndef NO_AUDIO
[6648]1120    "Wav",
1121    "mp3",
1122    "ogg",
[5306]1123#endif
[6648]1124#ifndef NO_TEXTURES
1125    "Texture",
[5306]1126#endif
[5323]1127#ifndef NO_SHADERS
[6648]1128    "Shader",
[5323]1129#endif
[6648]1130
1131  };
Note: See TracBrowser for help on using the repository browser.