Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 7235 was 7225, checked in by bensch, 19 years ago

orxonox/trunk: more std::string

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