Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 6650 was 6650, checked in by bensch, 20 years ago

trunk: cache bools

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