Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 3660 was 3660, checked in by bensch, 21 years ago

orxonox/trunk: now ResourceManager has the ability to unload resources by priority

File size: 10.5 KB
Line 
1/*
2   orxonox - the future of 3D-vertical-scrollers
3
4   Copyright (C) 2004 orx
5
6   This program is free software; you can redistribute it and/or modify
7   it under the terms of the GNU General Public License as published by
8   the Free Software Foundation; either version 2, or (at your option)
9   any later version.
10
11   ### File Specific:
12   main-programmer: Benjamin Grauer
13   co-programmer: ...
14*/
15
16#define DEBUG_SPECIAL_MODULE DEBUG_MODULE_LOAD
17
18#include "resource_manager.h"
19
20// different resource Types
21#include "objModel.h"
22#include "primitive_model.h"
23#include "texture.h"
24
25#include "list.h"
26
27// File Handling Includes
28#include <sys/types.h>
29#include <sys/stat.h>
30#include <unistd.h>
31
32using namespace std;
33
34/**
35   \brief standard constructor
36*/
37ResourceManager::ResourceManager () 
38{
39   this->setClassName ("ResourceManager");
40   dataDir = NULL;
41   imageDirs = new tList<char>();
42   resourceList = new tList<Resource>();
43}
44
45/**
46   \returns the Instance to this ResourceManager
47*/
48ResourceManager* ResourceManager::getInstance(void)
49{
50  if (!ResourceManager::singletonRef)
51    ResourceManager::singletonRef = new ResourceManager();
52  return ResourceManager::singletonRef;
53}
54
55//! Singleton Reference to the ResourceManager
56ResourceManager* ResourceManager::singletonRef = NULL;
57//! The List of Resources, that has already been loaded.
58tList<Resource>* ResourceManager::resourceList = NULL;
59//! The Data Directory, where all relevant Data is stored.
60char* ResourceManager::dataDir = NULL;
61//! A list of directories in which images are stored.
62tList<char>* ResourceManager::imageDirs = NULL;
63
64/**
65   \brief standard destructor
66*/
67ResourceManager::~ResourceManager (void) 
68{
69  // deleting the Resources-List
70  unloadAllByPriority(RP_GAME);
71  delete resourceList;
72  resourceList = NULL;
73  // deleting the Directorie Lists
74  char* tmpDir = imageDirs->enumerate();
75  while(tmpDir)
76    {
77      delete []tmpDir;
78      tmpDir = imageDirs->nextElement();
79    }
80
81  delete imageDirs;
82  imageDirs = NULL;
83  ResourceManager::singletonRef = NULL;
84}
85
86/**
87   \brief sets the data main directory
88   \param dataDir the DataDirectory.
89*/
90bool ResourceManager::setDataDir(char* dataDir)
91{
92  if (isDir(dataDir))
93    {
94      ResourceManager::dataDir = new char[strlen(dataDir)+1];
95      strcpy(ResourceManager::dataDir, dataDir);
96    }
97  else
98    {
99      PRINTF(1)("%s is not a Directory, and can not be the Data Directory\n", dataDir);
100    }
101}
102
103/**
104   \brief adds a new Path for Images
105   \param imageDir The path to insert
106   \returns true, if the Path was well and injected (or already existent within the list)
107   false otherwise
108*/
109bool ResourceManager::addImageDir(char* imageDir)
110{
111  // check if the param is a Directory
112  if (isDir(imageDir))
113    {
114      // check if the Directory has been added before
115      char* tmpDir = imageDirs->enumerate();
116      while(tmpDir)
117        {
118          if (!strcmp(tmpDir, imageDir))
119            {
120              PRINTF(4)("Path %s already loaded\n", imageDir);
121              return true;
122            }
123          tmpDir = imageDirs->nextElement();
124        }
125      // adding the directory to the List
126      tmpDir  = new char[strlen(imageDir)+1];
127      strcpy(tmpDir, imageDir);
128      imageDirs->add(tmpDir);
129      return true;
130    }
131  else
132    {
133      PRINTF(1)("%s is not a Directory, and can not be added to the Paths of Images\n", dataDir);
134      return false;
135    }
136}
137
138/**
139   \brief loads resources
140   \param fileName The fileName of the resource to load
141   \param prio The ResourcePriority of this resource (will only be increased)
142   \returns a pointer to a desired Resource.
143*/
144void* ResourceManager::load(const char* fileName, ResourcePriority prio)
145{
146  ResourceType tmpType;
147  if (!strncmp(fileName+(strlen(fileName)-4), ".obj", 4))
148    tmpType = OBJ;
149  else if (!strncmp(fileName+(strlen(fileName)-4), ".wav", 4))
150    tmpType = WAV;
151  else if (!strncmp(fileName+(strlen(fileName)-4), ".mp3", 4))
152    tmpType = MP3;
153  else if (!strncmp(fileName+(strlen(fileName)-4), ".ogg", 4))
154    tmpType = OGG;
155  else if (!strcmp(fileName, "cube") ||
156           !strcmp(fileName, "sphere") ||
157           !strcmp(fileName, "plane") ||
158           !strcmp(fileName, "cylinder") ||
159           !strcmp(fileName, "cone"))
160    tmpType = PRIM;
161  else 
162    tmpType = IMAGE;
163
164  return ResourceManager::load(fileName, tmpType, prio);
165}
166
167/**
168   \brief loads resources
169   \param fileName The fileName of the resource to load
170   \param type The Type of Resource to load (\see ResourceType)
171   \param prio The ResourcePriority of this resource (will only be increased)
172   \returns a pointer to a desired Resource.
173*/
174void* ResourceManager::load(const char* fileName, ResourceType type, ResourcePriority prio)
175{
176  // searching if the resource was loaded before.
177  Resource* tmpResource = ResourceManager::locateResourceByName(fileName);
178  if (!tmpResource) // if the resource was not loaded before.
179    {
180      char* tmpDir;
181      // Setting up the new Resource
182      tmpResource = new Resource;
183      tmpResource->count = 1;
184      tmpResource->type = type;
185      tmpResource->prio = prio;
186      tmpResource->name = new char[strlen(fileName)+1];
187      strcpy(tmpResource->name, fileName);
188
189      // creating the full name. (directoryName + FileName)
190      char* fullName = new char[strlen(dataDir)+strlen(fileName)+1];
191      sprintf(fullName, "%s%s", dataDir, fileName);
192     
193      // Checking for the type of resource \see ResourceType
194      switch(type)
195        {
196        case OBJ:
197          if(isFile(fullName))
198            tmpResource->pointer = new OBJModel(fullName);
199          else
200            {
201              PRINTF(2)("Sorry, %s does not exist. Loading a cube-Model instead\n", fullName);
202              tmpResource->pointer = ResourceManager::load("cube", PRIM);
203            }
204          break;
205        case PRIM:
206          if (!strcmp(tmpResource->name, "cube"))
207            tmpResource->pointer = new PrimitiveModel(CUBE);
208          else if (!strcmp(tmpResource->name, "sphere"))
209            tmpResource->pointer = new PrimitiveModel(SPHERE);
210          else if (!strcmp(tmpResource->name, "plane"))
211            tmpResource->pointer = new PrimitiveModel(PLANE);
212          else if (!strcmp(tmpResource->name, "cylinder"))
213            tmpResource->pointer = new PrimitiveModel(CYLINDER);
214          else if (!strcmp(tmpResource->name, "cone"))
215            tmpResource->pointer = new PrimitiveModel(CONE);
216          break;
217        case IMAGE:
218          if(isFile(fullName))
219            {
220              tmpResource->pointer = new Texture(fullName);
221            }
222          else
223            {
224              tmpDir = imageDirs->enumerate();
225              while(tmpDir)
226                {
227                  char* imgName = new char[strlen(tmpDir)+strlen(fileName)+1];
228                  sprintf(imgName, "%s%s", tmpDir, fileName);
229                  if(isFile(imgName))
230                    tmpResource->pointer = new Texture(imgName);
231                  delete []imgName;
232                  tmpDir = imageDirs->nextElement();
233                }
234            }
235          if(!tmpResource)
236             PRINTF(2)("!!Image %s not Found!!\n", fileName);
237          break;
238        default:
239          tmpResource->pointer = NULL;
240          PRINTF(1)("No type found for %s.\n   !!This should not happen unless the Type is not supported yet.!!\n", tmpResource->name);
241          break;
242        }
243     
244      // checking if the File really exists.
245      if(!isFile(fullName))
246        {
247          PRINTF(2)("Sorry, %s is not a regular file.\n", fullName);
248          tmpResource->pointer = NULL;
249        }
250      resourceList->add(tmpResource);
251      delete []fullName;
252    }
253  else
254    {
255      tmpResource->count++;
256      if(tmpResource->prio < prio)
257        tmpResource->prio = prio;
258    }
259
260  return tmpResource->pointer;
261}
262
263/**
264   \brief unloads a Resource
265   \param pointer The pointer to free
266   \returns true if successful (pointer found, and deleted), false otherwise
267   
268*/
269bool ResourceManager::unload(void* pointer, ResourcePriority prio)
270{
271  // if pointer is existent. and only one resource of this type exists.
272  Resource* tmpResource =ResourceManager::locateResourceByPointer(pointer);
273  if (!tmpResource)
274    {
275      PRINTF(2)("Resource not Found %p\n", pointer);
276      return false;
277    }
278  else
279    unload(tmpResource, prio);
280}
281
282bool ResourceManager::unload(Resource* resource, ResourcePriority prio)
283{
284  resource->count--;
285  if (resource->prio <= prio)
286    {
287      if (resource->count <= 0)
288        {
289          // deleting the Resource
290          switch(resource->type)
291            {
292            case OBJ:
293            case PRIM:
294              delete (Model*)resource->pointer;
295              break;
296            case IMAGE:
297              delete (Texture*)resource->pointer;
298              break;
299            default:
300              PRINTF(1)("NOT YET IMPLEMENTED !!FIX FIX!!\n");
301              return false;
302              break;
303            }
304          // deleting the List Entry:
305          PRINTF(4)("Resource %s safely removed.\n", resource->name);
306          delete []resource->name;
307          resourceList->remove(resource);
308        }
309      else
310        PRINTF(4)("Resource %s not removed, because there are still %d References to it.\n", resource->name, resource->count);
311    }
312  else
313    PRINTF(4)("not deleting resource %s because DeleteLevel to high\n", resource->name);
314  return true;
315}
316
317
318/**
319   \brief unloads all alocated Memory of Resources with a pririty lower than prio
320   \param prio The priority to delete
321*/
322bool ResourceManager::unloadAllByPriority(ResourcePriority prio)
323{
324  Resource* enumRes = resourceList->enumerate();
325  while (enumRes)
326    {
327      if (enumRes->prio <= prio)
328        unload(enumRes, prio);
329      enumRes = resourceList->nextElement();
330    }
331}
332
333/**
334   \brief Searches for a Resource by Name
335   \param fileName The name to look for
336   \returns a Pointer to the Resource if found, NULL otherwise.
337*/
338Resource* ResourceManager::locateResourceByName(const char* fileName)
339{
340  Resource* enumRes = resourceList->enumerate();
341  while (enumRes)
342    {
343      if (!strcmp(fileName, enumRes->name))
344        return enumRes;
345      enumRes = resourceList->nextElement();
346    }
347  return NULL;
348}
349
350/**
351   \brief Searches for a Resource by Pointer
352   \param pointer the Pointer to search for
353   \returns a Pointer to the Resource if found, NULL otherwise.
354*/
355Resource* ResourceManager::locateResourceByPointer(const void* pointer)
356{
357  Resource* enumRes = resourceList->enumerate();
358  while (enumRes)
359    {
360      if (pointer == enumRes->pointer);
361        return enumRes;
362      enumRes = resourceList->nextElement();
363    }
364  return NULL;
365}
366
367/**
368   \brief Checks if it is a Directory
369   \param directoryName the Directory to check for
370   \returns true if it is a directory/symlink false otherwise
371*/
372bool ResourceManager::isDir(const char* directoryName)
373{
374  struct stat status;
375  stat(directoryName, &status);
376  if (status.st_mode & (S_IFDIR | S_IFLNK))
377    return true;
378  else
379    return false;
380}
381
382/**
383   \brief Checks if the file is either a Regular file or a Symlink
384   \param fileName the File to check for
385   \returns true if it is a regular file/symlink, false otherwise
386*/
387bool ResourceManager::isFile(const char* fileName)
388{
389  struct stat status;
390  stat(fileName, &status);
391  if (status.st_mode & (S_IFREG | S_IFLNK))
392    return true;
393  else
394    return false;
395}
Note: See TracBrowser for help on using the repository browser.