Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

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

fromResourceableStrin and toResourceableString

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

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