Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/orxonox/branches/textEngine/src/lib/util/resource_manager.cc @ 3783

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

orxonox/branches/textEngine: now the Resource Manager also checks for special parameters

File size: 15.6 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: Patrick Boenzli
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#include "text_engine.h"
25
26#include "list.h"
27
28// File Handling Includes
29#include <sys/types.h>
30#include <sys/stat.h>
31#include <unistd.h>
32
33using namespace std;
34
35/**
36   \brief standard constructor
37*/
38ResourceManager::ResourceManager () 
39{
40   this->setClassName ("ResourceManager");
41   this->dataDir = "./";
42   this->imageDirs = new tList<char>();
43   this->resourceList = new tList<Resource>();
44}
45
46/**
47   \returns the Instance to this ResourceManager
48*/
49ResourceManager* ResourceManager::getInstance(void)
50{
51  if (!ResourceManager::singletonRef)
52    ResourceManager::singletonRef = new ResourceManager();
53  return ResourceManager::singletonRef;
54}
55
56//! Singleton Reference to the ResourceManager
57ResourceManager* ResourceManager::singletonRef = NULL;
58
59/**
60   \brief standard destructor
61*/
62ResourceManager::~ResourceManager (void) 
63{
64  // deleting the Resources-List
65  this->unloadAllByPriority(RP_GAME);
66  delete this->resourceList;
67  // deleting the Directorie Lists
68  tIterator<char>* tmpIt = imageDirs->getIterator();
69  char* tmpDir = tmpIt->nextElement();
70  while(tmpDir)
71    {
72      delete []tmpDir;
73      tmpDir = tmpIt->nextElement();
74    }
75  delete tmpIt;
76
77  delete this->imageDirs;
78
79  ResourceManager::singletonRef = NULL;
80}
81
82/**
83   \brief sets the data main directory
84   \param dataDir the DataDirectory.
85*/
86bool ResourceManager::setDataDir(char* dataDir)
87{
88  if (isDir(dataDir))
89    {
90      this->dataDir = new char[strlen(dataDir)+1];
91      strcpy(this->dataDir, dataDir);
92    }
93  else
94    {
95      PRINTF(1)("%s is not a Directory, and can not be the Data Directory\n", dataDir);
96    }
97}
98
99/**
100   \brief adds a new Path for Images
101   \param imageDir The path to insert
102   \returns true, if the Path was well and injected (or already existent within the list)
103   false otherwise
104*/
105bool ResourceManager::addImageDir(char* imageDir)
106{
107  // check if the param is a Directory
108  if (isDir(imageDir))
109    {
110      // check if the Directory has been added before
111      tIterator<char>* tmpImageDirs = imageDirs->getIterator();
112      char* tmpDir = tmpImageDirs->nextElement();
113      while(tmpDir)
114        {
115          if (!strcmp(tmpDir, imageDir))
116            {
117              PRINTF(4)("Path %s already loaded\n", imageDir);
118              delete tmpImageDirs;
119              return true;
120            }
121          tmpDir = tmpImageDirs->nextElement();
122        }
123      delete tmpImageDirs;
124
125      // adding the directory to the List
126      tmpDir  = new char[strlen(imageDir)+1];
127      strcpy(tmpDir, imageDir);
128      this->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, void* param1, void* param2, void* param3)
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 if (!strncmp(fileName+(strlen(fileName)-4), ".ttf", 4))
162    tmpType = TTF;
163  else 
164    tmpType = IMAGE;
165
166  return this->load(fileName, tmpType, prio, param1, param2, param3);
167}
168
169/**
170   \brief loads resources
171   \param fileName The fileName of the resource to load
172   \param type The Type of Resource to load (\see ResourceType)
173   \param prio The ResourcePriority of this resource (will only be increased)
174   \returns a pointer to a desired Resource.
175*/
176void* ResourceManager::load(const char* fileName, ResourceType type, ResourcePriority prio, void* param1, void* param2, void* param3)
177{
178  // searching if the resource was loaded before.
179  Resource* tmpResource = this->locateResourceByInfo(fileName, type, param1, param2,param3);
180  if (tmpResource) // if the resource was not loaded before.
181    {
182      PRINTF(4)("not loading cached resource %s\n", tmpResource->name);
183      tmpResource->count++;
184      if(tmpResource->prio < prio)
185        tmpResource->prio = prio;
186    }
187  else
188    {
189      char* tmpDir;
190      // Setting up the new Resource
191      tmpResource = new Resource;
192      tmpResource->count = 1;
193      tmpResource->type = type;
194      tmpResource->prio = prio;
195      tmpResource->name = new char[strlen(fileName)+1];
196      strcpy(tmpResource->name, fileName);
197
198      // creating the full name. (directoryName + FileName)
199      char* fullName = new char[strlen(dataDir)+strlen(fileName)+1];
200      sprintf(fullName, "%s%s", this->dataDir, fileName);
201     
202      // Checking for the type of resource \see ResourceType
203      switch(type)
204        {
205        case OBJ:
206          if (param1)
207            tmpResource->modelSize = *(float*)param1;
208          else
209            tmpResource->modelSize = 1.0;
210
211          if(isFile(fullName))
212            tmpResource->pointer = new OBJModel(fullName, tmpResource->modelSize);
213          else
214            {
215              PRINTF(2)("Sorry, %s does not exist. Loading a cube-Model instead\n", fullName);
216              tmpResource->pointer = ResourceManager::load("cube", PRIM, prio, &tmpResource->modelSize);
217            }
218          break;
219        case PRIM:
220          if (param1)
221            tmpResource->modelSize = *(float*)param1;
222          else
223            tmpResource->modelSize = 1.0;
224
225          if (!strcmp(tmpResource->name, "cube"))
226            tmpResource->pointer = new PrimitiveModel(CUBE, tmpResource->modelSize);
227          else if (!strcmp(tmpResource->name, "sphere"))
228            tmpResource->pointer = new PrimitiveModel(SPHERE, tmpResource->modelSize);
229          else if (!strcmp(tmpResource->name, "plane"))
230            tmpResource->pointer = new PrimitiveModel(PLANE, tmpResource->modelSize);
231          else if (!strcmp(tmpResource->name, "cylinder"))
232            tmpResource->pointer = new PrimitiveModel(CYLINDER, tmpResource->modelSize);
233          else if (!strcmp(tmpResource->name, "cone"))
234            tmpResource->pointer = new PrimitiveModel(CONE, tmpResource->modelSize);
235          break;
236        case TTF:
237            if (param1)
238              tmpResource->ttfSize = *(int*)param1;
239            else
240              tmpResource->ttfSize = FONT_DEFAULT_SIZE;
241            if (param2)
242              {
243                Vector* tmpVec = (Vector*)param2;
244                tmpResource->ttfColorR = (int)tmpVec->x;
245                tmpResource->ttfColorG = (int)tmpVec->y;
246                tmpResource->ttfColorB = (int)tmpVec->z;
247              }
248            else
249              {
250                tmpResource->ttfColorR = FONT_DEFAULT_COLOR_R;
251                tmpResource->ttfColorG = FONT_DEFAULT_COLOR_G;
252                tmpResource->ttfColorB = FONT_DEFAULT_COLOR_B;
253              }
254           
255          if(isFile(fullName))
256            tmpResource->pointer = new Font(fullName,
257                                            tmpResource->ttfSize,
258                                            tmpResource->ttfColorR,
259                                            tmpResource->ttfColorG,
260                                            tmpResource->ttfColorB);
261          else
262            PRINTF(2)("Sorry, %s does not exist. Not loading Font\n", fullName);
263          break;
264        case IMAGE:
265          if(isFile(fullName))
266            {
267              PRINTF(4)("Image %s resides to %s\n", fileName, fullName);
268              tmpResource->pointer = new Texture(fullName);
269            }
270          else
271            {
272              tIterator<char>* iterator = imageDirs->getIterator();
273              tmpDir = iterator->nextElement();
274              //tmpDir = imageDirs->enumerate();
275              while(tmpDir)
276                {
277                  char* imgName = new char[strlen(tmpDir)+strlen(fileName)+1];
278                  sprintf(imgName, "%s%s", tmpDir, fileName);
279                  if(isFile(imgName))
280                    {
281                      PRINTF(4)("Image %s resides to %s\n", fileName, imgName);
282                      tmpResource->pointer = new Texture(imgName);
283                      delete []imgName;
284                      break;
285                    }
286                  delete []imgName;
287                  tmpDir = iterator->nextElement();
288                }
289              delete iterator;
290            }
291          if(!tmpResource)
292             PRINTF(2)("!!Image %s not Found!!\n", fileName);
293          break;
294        default:
295          tmpResource->pointer = NULL;
296          PRINTF(1)("No type found for %s.\n   !!This should not happen unless the Type is not supported yet.!!\n", tmpResource->name);
297          break;
298        }
299      this->resourceList->add(tmpResource);
300      delete []fullName;
301    }
302  if (tmpResource->pointer)
303    return tmpResource->pointer;
304  else 
305    {
306      PRINTF(2)("Resource %s could not be loaded\n", fileName);
307      delete tmpResource;
308      return NULL;
309    }
310}
311
312/**
313   \brief unloads a Resource
314   \param pointer The pointer to free
315   \returns true if successful (pointer found, and deleted), false otherwise
316   
317*/
318bool ResourceManager::unload(void* pointer, ResourcePriority prio)
319{
320  // if pointer is existent. and only one resource of this type exists.
321  Resource* tmpResource = this->locateResourceByPointer(pointer);
322  if (!tmpResource)
323    {
324      PRINTF(2)("Resource not Found %p\n", pointer);
325      return false;
326    }
327  else
328    unload(tmpResource, prio);
329}
330
331bool ResourceManager::unload(Resource* resource, ResourcePriority prio)
332{
333  if (resource->count > 0)
334    resource->count--;
335  if (resource->prio <= prio)
336    {
337      if (resource->count <= 0)
338        {
339          // deleting the Resource
340          switch(resource->type)
341            {
342            case OBJ:
343            case PRIM:
344              delete (Model*)resource->pointer;
345              break;
346            case IMAGE:
347              delete (Texture*)resource->pointer;
348              break;
349            case TTF:
350              delete (Font*)resource->pointer;
351              break;
352            default:
353              PRINTF(1)("NOT YET IMPLEMENTED !!FIX FIX!!\n");
354              return false;
355              break;
356            }
357          // deleting the List Entry:
358          PRINTF(4)("Resource %s safely removed.\n", resource->name);
359          delete []resource->name;
360          this->resourceList->remove(resource);
361        }
362      else
363        PRINTF(4)("Resource %s not removed, because there are still %d References to it.\n", resource->name, resource->count);
364    }
365  else
366    PRINTF(4)("not deleting resource %s because DeleteLevel to high\n", resource->name);
367  return true;
368}
369
370
371/**
372   \brief unloads all alocated Memory of Resources with a pririty lower than prio
373   \param prio The priority to delete
374*/
375bool ResourceManager::unloadAllByPriority(ResourcePriority prio)
376{
377  tIterator<Resource>* iterator = resourceList->getIterator();
378  Resource* enumRes = iterator->nextElement();
379  while (enumRes)
380    {
381      if (enumRes->prio <= prio)
382        if (enumRes->count == 0)
383          unload(enumRes, prio);
384        else
385          PRINTF(2)("unable to unload %s because there are still %d references to it\n",
386                   enumRes->name, enumRes->count);
387      //enumRes = resourceList->nextElement();
388      enumRes = iterator->nextElement();
389    }
390  delete iterator;
391}
392
393/**
394   \brief Searches for a Resource by some information
395   \param fileName The name to look for
396   \returns a Pointer to the Resource if found, NULL otherwise.
397*/
398Resource* ResourceManager::locateResourceByInfo(const char* fileName, ResourceType type, void* param1, void* param2, void* param3)
399{
400  //  Resource* enumRes = resourceList->enumerate();
401  tIterator<Resource>* iterator = resourceList->getIterator();
402  Resource* enumRes = iterator->nextElement();
403  while (enumRes)
404    {
405      if (enumRes->type == type && !strcmp(fileName, enumRes->name))
406        {
407          bool match = false;
408          bool subMatch = false;
409          switch (type)
410            {
411            case PRIM:
412            case OBJ:
413              if (!param1)
414                {
415                  if (enumRes->modelSize == 1.0)
416                    match = true;
417                }
418              else if (enumRes->modelSize == *(float*)param1)
419                match = true;
420              break;
421            case TTF:
422              if (!param1)
423                {
424                  if (enumRes->ttfSize == FONT_DEFAULT_SIZE)
425                    subMatch = true;
426                }
427              else if (enumRes->modelSize =- *(int*)param1)
428                subMatch = true;
429              if(subMatch)
430                {
431                  Vector* tmpVec = (Vector*)param2;
432                  if (!param2)
433                    {
434                      if(enumRes->ttfColorR == FONT_DEFAULT_COLOR_R &&
435                         enumRes->ttfColorG == FONT_DEFAULT_COLOR_G &&
436                         enumRes->ttfColorB == FONT_DEFAULT_COLOR_B )
437                        match = true;
438                    }
439                  else if (enumRes->ttfColorR == (int)tmpVec->x &&
440                           enumRes->ttfColorG == (int)tmpVec->y &&
441                           enumRes->ttfColorB == (int)tmpVec->z )
442                    match = true;
443                }
444
445              break;
446            default:
447              match = true;
448              break;
449            }
450          if (match)
451            {
452              delete iterator;
453              return enumRes;
454            }
455        }
456      enumRes = iterator->nextElement();
457    }
458  delete iterator;
459  return NULL;
460}
461
462/**
463   \brief Searches for a Resource by Pointer
464   \param pointer the Pointer to search for
465   \returns a Pointer to the Resource if found, NULL otherwise.
466*/
467Resource* ResourceManager::locateResourceByPointer(const void* pointer)
468{
469  //  Resource* enumRes = resourceList->enumerate();
470  tIterator<Resource>* iterator = resourceList->getIterator();
471  Resource* enumRes = iterator->nextElement();
472  while (enumRes)
473    {
474      if (pointer == enumRes->pointer)
475        {
476          delete iterator;
477          return enumRes;
478        }
479      enumRes = iterator->nextElement();
480    }
481  delete iterator;
482  return NULL;
483}
484
485/**
486   \brief Checks if it is a Directory
487   \param directoryName the Directory to check for
488   \returns true if it is a directory/symlink false otherwise
489*/
490bool ResourceManager::isDir(const char* directoryName)
491{
492  struct stat status;
493  stat(directoryName, &status);
494  if (status.st_mode & (S_IFDIR
495#ifndef __WIN32__
496                        | S_IFLNK
497#endif
498                        ))
499    return true;
500  else
501    return false;
502}
503
504/**
505   \brief Checks if the file is either a Regular file or a Symlink
506   \param fileName the File to check for
507   \returns true if it is a regular file/symlink, false otherwise
508*/
509bool ResourceManager::isFile(const char* fileName)
510{
511  struct stat status;
512  stat(fileName, &status);
513  if (status.st_mode & (S_IFREG
514#ifndef __WIN32__
515                        | S_IFLNK
516#endif
517                        ))
518    return true;
519  else
520    return false;
521}
522
523/**
524   \brief outputs debug information about the ResourceManager
525*/
526void ResourceManager::debug(void)
527{
528  PRINT(0)("=RM===================================\n");
529  PRINT(0)("= RESOURCE-MANAGER DEBUG INFORMATION =\n");
530  PRINT(0)("======================================\n");
531  // if it is not initialized
532  PRINT(0)(" Reference is: %p\n", ResourceManager::singletonRef);
533  PRINT(0)(" Data-Directory is: %s\n", this->dataDir);
534  PRINT(0)(" List of Image-Directories: ");
535  tIterator<char>* tmpIt = imageDirs->getIterator();
536  char* tmpDir = tmpIt->nextElement();
537  while(tmpDir)
538    {
539      PRINT(0)("%s ",tmpDir);
540      tmpDir = tmpIt->nextElement();
541    }
542  delete tmpIt;
543  PRINT(0)("\n");
544
545  PRINT(0)("List of all stored Resources:\n");
546  tIterator<Resource>* iterator = resourceList->getIterator();
547  Resource* enumRes = iterator->nextElement();
548  while (enumRes)
549    {
550      PRINT(0)("-----------------------------------------\n");
551      PRINT(0)("Name: %s; References: %d; Type:", enumRes->name, enumRes->count);
552      switch (enumRes->type)
553        {
554        case OBJ:
555          PRINT(0)("ObjectModel\n");
556          break;
557        case PRIM:
558          PRINT(0)("PrimitiveModel\n");
559          break;
560        case IMAGE:
561          PRINT(0)("ImageFile (Texture)\n");
562          break;
563        default:
564          PRINT(0)("SoundFile\n");
565          break;
566        }
567      PRINT(0)("gets deleted at ");
568      switch(enumRes->prio)
569        {
570        default:
571        case RP_NO:
572          PRINT(0)("first posibility (0)\n");
573          break;
574        case RP_LEVEL:
575          PRINT(0)("the end of the Level (1)\n");
576          break;
577        case RP_CAMPAIGN:
578          PRINT(0)("the end of the campaign (2)\n");
579          break;
580        case RP_GAME:
581          PRINT(0)("when leaving the game (3)\n");
582          break;
583        }
584      enumRes = iterator->nextElement();
585    }
586  delete iterator;
587
588
589
590  PRINT(0)("==================================RM==\n");
591}
Note: See TracBrowser for help on using the repository browser.