/* orxonox - the future of 3D-vertical-scrollers Copyright (C) 2004 orx This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. ### File Specific: main-programmer: Benjamin Grauer co-programmer: Patrick Boenzli */ #define DEBUG_SPECIAL_MODULE DEBUG_MODULE_LOAD #include "resource_manager.h" #include "substring.h" #include "debug.h" #include #include // different resource Types #ifndef NO_MODEL #include "objModel.h" #include "primitive_model.h" #include "md2Model.h" #endif /* NO_MODEL */ #ifndef NO_TEXTURES #include "texture.h" #endif /* NO_TEXTURES */ #ifndef NO_TEXT #include "font.h" #endif /* NO_TEXT */ #ifndef NO_AUDIO #include "sound_buffer.h" #include "ogg_player.h" #endif /* NO_AUDIO */ #ifndef NO_SHADERS #include "shader.h" #endif /* NO_SHADERS */ // File Handling Includes #include #include #include using namespace std; /** * @brief standard constructor */ ResourceManager::ResourceManager () { this->setClassID(CL_RESOURCE_MANAGER, "ResourceManager"); this->setName("ResourceManager"); this->dataDir = new char[3]; strcpy(this->dataDir, "./"); this->tryDataDir("./data"); } //! Singleton Reference to the ResourceManager ResourceManager* ResourceManager::singletonRef = NULL; /** * @brief standard destructor */ ResourceManager::~ResourceManager () { // deleting the Resources-List this->unloadAllByPriority(RP_GAME); if (!this->resourceList.empty()) PRINTF(1)("Not removed all Resources, since there are still %d resources registered\n", this->resourceList.size()); // deleting the Directorie Lists while (!this->imageDirs.empty()) { delete[] this->imageDirs.back(); this->imageDirs.pop_back(); } delete[] this->dataDir; ResourceManager::singletonRef = NULL; } /** * @brief sets the data main directory * @param dataDir the DataDirectory. */ bool ResourceManager::setDataDir(const char* dataDir) { char* realDir = ResourceManager::homeDirCheck(dataDir); if (isDir(realDir)) { delete[] this->dataDir; if (dataDir[strlen(dataDir)-1] == '/' || dataDir[strlen(dataDir)-1] == '\\') { this->dataDir = new char[strlen(realDir)+1]; strcpy(this->dataDir, realDir); } else { this->dataDir = new char[strlen(realDir)+2]; strcpy(this->dataDir, realDir); this->dataDir[strlen(realDir)] = '/'; this->dataDir[strlen(realDir)+1] = '\0'; } delete[] realDir; return true; } else { PRINTF(1)("%s is not a Directory, and can not be the Data Directory, leaving as %s \n", realDir, this->dataDir); delete[] realDir; return false; } } /** * @brief sets the data main directory * @param dataDir the DataDirectory. * * this is essentially the same as setDataDir, but it ommits the error-message */ bool ResourceManager::tryDataDir(const char* dataDir) { char* realDir = ResourceManager::homeDirCheck(dataDir); if (isDir(realDir)) { delete[] this->dataDir; if (dataDir[strlen(dataDir)-1] == '/' || dataDir[strlen(dataDir)-1] == '\\') { this->dataDir = new char[strlen(realDir)+1]; strcpy(this->dataDir, realDir); } else { this->dataDir = new char[strlen(realDir)+2]; strcpy(this->dataDir, realDir); this->dataDir[strlen(realDir)] = '/'; this->dataDir[strlen(realDir)+1] = '\0'; } delete[] realDir; return true; } delete[] realDir; return false; } /** * @brief checks for the DataDirectory, by looking if * @param fileInside is iniside of the given directory. */ bool ResourceManager::verifyDataDir(const char* fileInside) { bool retVal; if (!isDir(this->dataDir)) { PRINTF(1)("%s is not a directory\n", this->dataDir); return false; } char* testFile = new char[strlen(this->dataDir)+strlen(fileInside)+1]; sprintf(testFile, "%s%s", this->dataDir, fileInside); retVal = isFile(testFile); delete[] testFile; return retVal; } #ifndef NO_TEXTURES /** * @brief adds a new Path for Images * @param imageDir The path to insert * @returns true, if the Path was well and injected (or already existent within the list) false otherwise */ bool ResourceManager::addImageDir(const char* imageDir) { if (imageDir == NULL) return false; char* newDir; if (imageDir[strlen(imageDir)-1] == '/' || imageDir[strlen(imageDir)-1] == '\\') { newDir = new char[strlen(imageDir)+1]; strcpy(newDir, imageDir); } else { newDir = new char[strlen(imageDir)+2]; strcpy(newDir, imageDir); newDir[strlen(imageDir)] = '/'; newDir[strlen(imageDir)+1] = '\0'; } // check if the param is a Directory if (isDir(newDir)) { // check if the Directory has been added before std::vector::const_iterator imageDir; for (imageDir = this->imageDirs.begin(); imageDir != this->imageDirs.end(); imageDir++) { if (!strcmp(*imageDir, newDir)) { PRINTF(3)("Path %s already loaded\n", newDir); delete[] newDir; return true; } } // adding the directory to the List this->imageDirs.push_back(newDir); return true; } else { PRINTF(1)("%s is not a Directory, and can not be added to the Paths of Images\n", newDir); delete[] newDir; return false; } } #endif /* NO_TEXTURES */ /** * @brief loads resources * @param fileName: The fileName of the resource to load * @param prio: The ResourcePriority of this resource (will only be increased) * @param param0: an additional option to parse (see the constuctors for more help) * @param param1: an additional option to parse (see the constuctors for more help) * @param param2: an additional option to parse (see the constuctors for more help) * @returns a pointer to a desired Resource. */ BaseObject* ResourceManager::load(const char* fileName, ResourcePriority prio, const MultiType& param0, const MultiType& param1, const MultiType& param2) { if (fileName == NULL) return NULL; ResourceType tmpType; #ifndef NO_MODEL #define __IF_OK if (!strncasecmp(fileName+(strlen(fileName)-4), ".obj", 4)) tmpType = OBJ; else if (!strncmp(fileName+(strlen(fileName)-4), ".md2", 4)) tmpType = MD2; else if (!strcasecmp(fileName, "cube") || !strcasecmp(fileName, "sphere") || !strcasecmp(fileName, "plane") || !strcasecmp(fileName, "cylinder") || !strcasecmp(fileName, "cone")) tmpType = PRIM; #endif /* NO_MODEL */ #ifndef NO_AUDIO #ifdef __IF_OK else #endif #define __IF_OK if (!strncasecmp(fileName+(strlen(fileName)-4), ".wav", 4)) tmpType = WAV; else if (!strncasecmp(fileName+(strlen(fileName)-4), ".mp3", 4)) tmpType = MP3; else if (!strncasecmp(fileName+(strlen(fileName)-4), ".ogg", 4)) tmpType = OGG; #endif /* NO_AUDIO */ #ifndef NO_TEXT #ifdef __IF_OK else #endif #define __IF_OK if (!strncasecmp(fileName+(strlen(fileName)-4), ".ttf", 4)) tmpType = TTF; #endif /* NO_TEXT */ #ifndef NO_SHADERS #ifdef __IF_OK else #endif #define __IF_OK if (!strncasecmp(fileName+(strlen(fileName)-5), ".vert", 5)) tmpType = SHADER; #endif /* NO_SHADERS */ #ifndef NO_TEXTURES #ifdef __IF_OK else #else if #endif tmpType = IMAGE; #endif /* NO_TEXTURES */ #undef __IF_OK return this->load(fileName, tmpType, prio, param0, param1, param2); } /** * @brief caches a Resource * * @see load; * * @brief returns true if ok, false otherwise. * This function loads a Resource without applying it to an Object. * This is for loading purposes, e.g, when the user is loading a Resource * during the initialisation instead of at Runtime. */ bool ResourceManager::cache(const char* fileName, ResourceType type, ResourcePriority prio, const MultiType& param0, const MultiType& param1, const MultiType& param2) { assert(fileName != NULL); // searching if the resource was loaded before. Resource* tmpResource; // check if we already loaded this Resource tmpResource = this->locateResourceByInfo(fileName, type, param0, param1, param2); // otherwise load it if (tmpResource == NULL) tmpResource = this->loadResource(fileName, type, prio, param0, param1, param2); // return cached pointer. if (tmpResource != NULL) // if the resource was loaded before. { if(tmpResource->prio < prio) tmpResource->prio = prio; return true; } else return false; } /** * tells the ResourceManager to generate a Copy of the Resource. * @brief resourcePointer: The Pointer to the resource to copy * @returns the Resource pointed to resourcePointer. */ BaseObject* ResourceManager::copy(BaseObject* resourcePointer) { Resource* tmp = locateResourceByPointer(resourcePointer); if (tmp!=NULL) { tmp->count++; return tmp->pointer; } else return NULL; } /** * @brief loads resources * @param fileName: The fileName of the resource to load * @param type: The Type of Resource to load. * @param prio: The ResourcePriority of this resource (will only be increased) * @param param0: an additional option to parse (see the constuctors for more help) * @param param1: an additional option to parse (see the constuctors for more help) * @param param2: an additional option to parse (see the constuctors for more help) * @returns a pointer to a desired Resource. */ BaseObject* ResourceManager::load(const char* fileName, ResourceType type, ResourcePriority prio, const MultiType& param0, const MultiType& param1, const MultiType& param2) { assert(fileName != NULL); // searching if the resource was loaded before. Resource* tmpResource; // check if we already loaded this Resource tmpResource = this->locateResourceByInfo(fileName, type, param0, param1, param2); // otherwise load it if (tmpResource == NULL) { tmpResource = this->loadResource(fileName, type, prio, param0, param1, param2); } // return cached pointer. if (tmpResource != NULL) // if the resource was loaded before. { tmpResource->count++; if(tmpResource->prio < prio) tmpResource->prio = prio; return tmpResource->pointer; } else return NULL; } /** * @brief loads resources for internal purposes * @param fileName: The fileName of the resource to load * @param type: The Type of Resource to load. * @param prio: The ResourcePriority of this resource (will only be increased) * @param param0: an additional option to parse (see the constuctors for more help) * @param param1: an additional option to parse (see the constuctors for more help) * @param param2: an additional option to parse (see the constuctors for more help) * @returns a pointer to a desired Resource. */ Resource* ResourceManager::loadResource(const char* fileName, ResourceType type, ResourcePriority prio, const MultiType& param0, const MultiType& param1, const MultiType& param2) { // Setting up the new Resource Resource* tmpResource = new Resource; tmpResource->count = 0; tmpResource->type = type; tmpResource->prio = prio; tmpResource->pointer = NULL; tmpResource->name = new char[strlen(fileName)+1]; strcpy(tmpResource->name, fileName); // creating the full name. (directoryName + FileName) char* fullName = ResourceManager::getFullName(fileName); // Checking for the type of resource \see ResourceType switch(type) { #ifndef NO_MODEL case OBJ: if (param0.getType() != MT_NULL) tmpResource->param[0] = param0; else tmpResource->param[0] = 1.0f; if(ResourceManager::isFile(fullName)) tmpResource->pointer = new OBJModel(fullName, tmpResource->param[0].getFloat()); else { PRINTF(2)("File %s in %s does not exist. Loading a cube-Model instead\n", fileName, dataDir); tmpResource->pointer = ResourceManager::load("cube", PRIM, prio, tmpResource->param[0].getFloat()); } break; case PRIM: if (param0 != MT_NULL) tmpResource->param[0] = param0; else tmpResource->param[0] = 1.0f; if (!strcmp(tmpResource->name, "cube")) tmpResource->pointer = new PrimitiveModel(PRIM_CUBE, tmpResource->param[0].getFloat()); else if (!strcmp(tmpResource->name, "sphere")) tmpResource->pointer = new PrimitiveModel(PRIM_SPHERE, tmpResource->param[0].getFloat()); else if (!strcmp(tmpResource->name, "plane")) tmpResource->pointer = new PrimitiveModel(PRIM_PLANE, tmpResource->param[0].getFloat()); else if (!strcmp(tmpResource->name, "cylinder")) tmpResource->pointer = new PrimitiveModel(PRIM_CYLINDER, tmpResource->param[0].getFloat()); else if (!strcmp(tmpResource->name, "cone")) tmpResource->pointer = new PrimitiveModel(PRIM_CONE, tmpResource->param[0].getFloat()); break; case MD2: if(ResourceManager::isFile(fullName)) { tmpResource->param[0] = param0; tmpResource->pointer = new MD2Data(fullName, tmpResource->param[0].getString()); // tmpResource->pointer = new MD2Model(fullName, tmpResource->secFileName); } break; #endif /* NO_MODEL */ #ifndef NO_TEXT case TTF: if (param0 != MT_NULL) { assert(param0.getInt() >= 0); tmpResource->param[0] = param0; } else tmpResource->param[0] = FONT_DEFAULT_RENDER_SIZE; if(isFile(fullName)) tmpResource->pointer = new Font(fullName, (unsigned int) tmpResource->param[0].getInt()); else PRINTF(2)("%s does not exist in %s. Not loading Font\n", fileName, this->dataDir); break; #endif /* NO_TEXT */ #ifndef NO_AUDIO case WAV: if(isFile(fullName)) tmpResource->pointer = new SoundBuffer(fullName); break; case OGG: if (isFile(fullName)) tmpResource->pointer = new OggPlayer(fullName); break; #endif /* NO_AUDIO */ #ifndef NO_TEXTURES case IMAGE: if (param0 != MT_NULL) tmpResource->param[0] = param0; else tmpResource->param[0] = GL_TEXTURE_2D; if(isFile(fullName)) { PRINTF(4)("Image %s resides to %s\n", fileName, fullName); tmpResource->pointer = new Texture(fullName); } else { std::vector::iterator imageDir; for (imageDir = this->imageDirs.begin(); imageDir != this->imageDirs.end(); imageDir++) { char* imgName = new char[strlen(*imageDir)+strlen(fileName)+1]; sprintf(imgName, "%s%s", *imageDir, fileName); if(isFile(imgName)) { PRINTF(4)("Image %s resides to %s\n", fileName, imgName); tmpResource->pointer = new Texture(imgName, tmpResource->param[0].getInt()); delete[] imgName; break; } delete[] imgName; } } if(!tmpResource) PRINTF(2)("!!Image %s not Found!!\n", fileName); break; #endif /* NO_TEXTURES */ #ifndef NO_SHADERS case SHADER: if(ResourceManager::isFile(fullName)) { if (param0 != MT_NULL) { MultiType param = param0; /// HACK char* secFullName = ResourceManager::getFullName(param.getString()); if (ResourceManager::isFile(secFullName)) { tmpResource->param[0] = secFullName; tmpResource->pointer = new Shader(fullName, secFullName); } delete[] secFullName; } else { tmpResource->param[0] = param0; tmpResource->pointer = new Shader(fullName, NULL); } } break; #endif /* NO_SHADERS */ default: tmpResource->pointer = NULL; 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); break; } if (tmpResource->pointer != NULL) this->resourceList.push_back(tmpResource); delete[] fullName; if (tmpResource->pointer != NULL) return tmpResource; else { PRINTF(2)("Resource %s could not be loaded\n", fileName); delete[] tmpResource->name; delete tmpResource; return NULL; } } /** * @brief unloads a Resource * @param pointer: The pointer to free * @param prio: the PriorityLevel to unload this resource * @returns true if successful (pointer found, and deleted), false otherwise */ bool ResourceManager::unload(BaseObject* pointer, ResourcePriority prio) { if (pointer == NULL) return false; // if pointer is existent. and only one resource of this type exists. Resource* tmpResource = this->locateResourceByPointer(pointer); if (tmpResource != NULL) return unload(tmpResource, prio); else { PRINTF(2)("Resource not Found %p\n", pointer); return false; } } /** * @brief unloads a Resource * @param resource: The resource to unloade * @param prio the PriorityLevel to unload this resource * @returns true on success, false otherwise. */ bool ResourceManager::unload(Resource* resource, ResourcePriority prio) { if (resource == NULL) return false; if (resource->count > 0) resource->count--; if (resource->prio <= prio) { if (resource->count == 0) { // deleting the Resource switch(resource->type) { #ifndef NO_MODEL case OBJ: case PRIM: delete (Model*)resource->pointer; break; case MD2: delete (MD2Data*)resource->pointer; break; #endif /* NO_MODEL */ #ifndef NO_AUDIO case WAV: delete (SoundBuffer*)resource->pointer; break; case OGG: delete (OggPlayer*)resource->pointer; break; #endif /* NO_AUDIO */ #ifndef NO_TEXT case TTF: delete (Font*)resource->pointer; break; #endif /* NO_TEXT */ #ifndef NO_TEXTURES case IMAGE: delete (Texture*)resource->pointer; break; #endif /* NO_TEXTURES */ #ifndef NO_SHADERS case SHADER: delete (Shader*)resource->pointer; break; #endif /* NO_SHADERS */ default: PRINTF(2)("NOT YET IMPLEMENTED !!FIX FIX!!\n"); return false; break; } // deleting the List Entry: PRINTF(4)("Resource %s safely removed.\n", resource->name); delete[] resource->name; std::vector::iterator resourceIT = std::find(this->resourceList.begin(), this->resourceList.end(), resource); this->resourceList.erase(resourceIT); delete resource; } else PRINTF(4)("Resource %s not removed, because there are still %d References to it.\n", resource->name, resource->count); } else PRINTF(4)("not deleting resource %s because DeleteLevel to high\n", resource->name); return true; } /** * @brief unloads all alocated Memory of Resources with a pririty lower than prio * @param prio The priority to delete */ bool ResourceManager::unloadAllByPriority(ResourcePriority prio) { unsigned int removeCount; for (unsigned int round = 0; round < 3; round++) { int index = this->resourceList.size() - 1; removeCount = 0; while (index >= 0) { if (this->resourceList[index]->prio <= prio) { if (this->resourceList[index]->count == 0) unload(this->resourceList[index], prio); else { PRINTF(2)("unable to unload %s because there are still %d references to it\n", this->resourceList[index]->name, this->resourceList[index]->count); removeCount++; } } index--; } if (removeCount == 0) break; } } /** * @brief Searches for a Resource by some information * @param fileName: The name to look for * @param type the Type of resource to locate. * @param param0: an additional option to parse (see the constuctors for more help) * @param param1: an additional option to parse (see the constuctors for more help) * @param param2: an additional option to parse (see the constuctors for more help) * @returns a Pointer to the Resource if found, NULL otherwise. */ Resource* ResourceManager::locateResourceByInfo(const char* fileName, ResourceType type, const MultiType& param0, const MultiType& param1, const MultiType& param2) const { std::vector::const_iterator resource; for (resource = this->resourceList.begin(); resource != this->resourceList.end(); resource++) { if ((*resource)->type == type && !strcmp(fileName, (*resource)->name)) { bool match = false; switch (type) { #ifndef NO_MODEL case PRIM: case OBJ: if (param0 == MT_NULL) { if ((*resource)->param[0] == 1.0f) match = true; } else if ((*resource)->param[0] == param0.getFloat()) match = true; break; case MD2: if (param0 == MT_NULL) { if ((*resource)->param[0] == "") match = true; } else if ((*resource)->param[0] == ((MultiType)param0).getString()) match = true; break; #endif /* NO_MODEL */ #ifndef NO_TEXT case TTF: if (param0 == MT_NULL) { if ((*resource)->param[0] == FONT_DEFAULT_RENDER_SIZE) match = true; } else if ((*resource)->param[0] == param0.getInt()) match = true; break; #endif /* NO_TEXT */ #ifndef NO_SHADERS case SHADER: if (param0 == MT_NULL) { if ((*resource)->param[0] == "") match = true; } else if ((*resource)->param[0] == ((MultiType)param0).getString()) match = true; #endif /* NO_SHADERS */ #ifndef NO_TEXTURES case IMAGE: if (param0 == MT_NULL) { if ((*resource)->param[0] == GL_TEXTURE_2D) match = true; } else if ((*resource)->param[0] == param0.getInt()) match = true; #endif /* NO_TEXTURES */ default: match = true; break; } if (match) { return (*resource); } } } return NULL; } /** * @brief Searches for a Resource by Pointer * @param pointer the Pointer to search for * @returns a Pointer to the Resource if found, NULL otherwise. */ Resource* ResourceManager::locateResourceByPointer(const void* pointer) const { // Resource* enumRes = resourceList->enumerate(); std::vector::const_iterator resource; for (resource = this->resourceList.begin(); resource != this->resourceList.end(); resource++) if (pointer == (*resource)->pointer) return (*resource); return NULL; } char* ResourceManager::toResourcableString(unsigned int i) { int len = strlen(ResourceManager::ResourceTypeToChar(this->resourceList[i]->type)); len += strlen(this->resourceList[i]->name); if (this->resourceList[i]->param[0].getString()) len += strlen(this->resourceList[i]->param[0].getString()) +1; if (this->resourceList[i]->param[1].getString()) len += strlen(this->resourceList[i]->param[1].getString()) +1; if (this->resourceList[i]->param[2].getString()) len += strlen(this->resourceList[i]->param[2].getString()) +1; len += 10; char* tmp = new char[len]; tmp[0] = '\0'; strcat( tmp, ResourceManager::ResourceTypeToChar(this->resourceList[i]->type)); strcat(tmp,","); strcat (tmp, this->resourceList[i]->name); if (this->resourceList[i]->param[0].getString() && this->resourceList[i]->param[0].getString() != '\0') { strcat(tmp,","); strcat( tmp, this->resourceList[i]->param[0].getString()); } if (this->resourceList[i]->param[1].getString() && this->resourceList[i]->param[1].getString() != '\0') { strcat(tmp,","); strcat( tmp, this->resourceList[i]->param[1].getString()); } if (this->resourceList[i]->param[2].getString() && this->resourceList[i]->param[2].getString() != '\0') { strcat(tmp,","); strcat( tmp, this->resourceList[i]->param[2].getString()); } return tmp; } /** * @brief caches a Resource from a ResourceableString created with the toResourcableString-function * @param resourceableString the String to cache the resource from. */ bool ResourceManager::fromResourceableString(const char* resourceableString) { SubString splits(resourceableString, ','); splits.debug(); if (splits.getCount() == 2) this->cache(splits[1], ResourceManager::stringToResourceType(splits[0]), RP_LEVEL); else if (splits.getCount() == 3) return this->cache(splits[1], ResourceManager::stringToResourceType(splits[0]), RP_LEVEL, splits[2]); else if (splits.getCount() == 4) return this->cache(splits[1], ResourceManager::stringToResourceType(splits[0]), RP_LEVEL, splits[2], splits[3]); else if (splits.getCount() == 5) return this->cache(splits[1], ResourceManager::stringToResourceType(splits[0]), RP_LEVEL, splits[2], splits[3], splits[4]); } /** * @brief Checks if it is a Directory * @param directoryName the Directory to check for * @returns true if it is a directory/symlink false otherwise */ bool ResourceManager::isDir(const char* directoryName) { if (directoryName == NULL) return false; char* tmpDirName = NULL; struct stat status; // checking for the termination of the string given. If there is a "/" at the end cut it away if (directoryName[strlen(directoryName)-1] == '/' || directoryName[strlen(directoryName)-1] == '\\') { tmpDirName = new char[strlen(directoryName)]; strncpy(tmpDirName, directoryName, strlen(directoryName)-1); tmpDirName[strlen(directoryName)-1] = '\0'; } else { tmpDirName = new char[strlen(directoryName)+1]; strcpy(tmpDirName, directoryName); } if(!stat(tmpDirName, &status)) { if (status.st_mode & (S_IFDIR #ifndef __WIN32__ | S_IFLNK #endif )) { delete[] tmpDirName; return true; } else { delete[] tmpDirName; return false; } } else { delete[] tmpDirName; return false; } } /** * @brief Checks if the file is either a Regular file or a Symlink * @param fileName the File to check for * @returns true if it is a regular file/symlink, false otherwise */ bool ResourceManager::isFile(const char* fileName) { if (fileName == NULL) return false; char* tmpFileName = ResourceManager::homeDirCheck(fileName); // actually checks the File struct stat status; if (!stat(tmpFileName, &status)) { if (status.st_mode & (S_IFREG #ifndef __WIN32__ | S_IFLNK #endif )) { delete[] tmpFileName; return true; } else { delete[] tmpFileName; return false; } } else { delete[] tmpFileName; return false; } } /** * @brief touches a File on the disk (thereby creating it) * @param fileName The file to touch */ bool ResourceManager::touchFile(const char* fileName) { char* tmpName = ResourceManager::homeDirCheck(fileName); if (tmpName == NULL) return false; FILE* stream; if( (stream = fopen (tmpName, "w")) == NULL) { PRINTF(1)("could not open %s fro writing\n", fileName); delete[] tmpName; return false; } fclose(stream); delete[] tmpName; } /** * @brief deletes a File from disk * @param fileName the File to delete */ bool ResourceManager::deleteFile(const char* fileName) { if (fileName == NULL) return false; char* tmpName = ResourceManager::homeDirCheck(fileName); unlink(tmpName); delete[] tmpName; } /** * @param name the Name of the file to check * @returns The name of the file, including the HomeDir * IMPORTANT: this has to be deleted from the outside */ char* ResourceManager::homeDirCheck(const char* name) { if (name == NULL) return NULL; char* retName; if (!strncmp(name, "~/", 2)) { char tmpFileName[500]; #ifdef __WIN32__ strcpy(tmpFileName, getenv("USERPROFILE")); #else strcpy(tmpFileName, getenv("HOME")); #endif retName = new char[strlen(tmpFileName)+strlen(name)]; sprintf(retName, "%s%s", tmpFileName, name+1); } else { retName = new char[strlen(name)+1]; strcpy(retName, name); } return retName; } /** * @param fileName the Name of the File to check * @returns The full name of the file, including the DataDir, and NULL if the file does not exist * !!IMPORTANT: this has to be deleted from the outside!! */ char* ResourceManager::getFullName(const char* fileName) { if (fileName == NULL || ResourceManager::getInstance()->getDataDir() == NULL) return NULL; char* retName = new char[strlen(ResourceManager::getInstance()->getDataDir()) + strlen(fileName) + 1]; sprintf(retName, "%s%s", ResourceManager::getInstance()->getDataDir(), fileName); if (ResourceManager::isFile(retName) || ResourceManager::isDir(retName)) return retName; else { delete[] retName; return NULL; } } /** * @brief checks wether a file is in the DataDir. * @param fileName the File to check if it is in the Data-Dir structure. * @returns true if the file exists, false otherwise */ bool ResourceManager::isInDataDir(const char* fileName) { if (fileName == NULL || ResourceManager::getInstance()->getDataDir() == NULL) return false; bool retVal = false; char* checkFile = new char[strlen(ResourceManager::getInstance()->getDataDir()) + strlen(fileName) + 1]; sprintf(checkFile, "%s%s", ResourceManager::getInstance()->getDataDir(), fileName); if (ResourceManager::isFile(checkFile) || ResourceManager::isDir(checkFile)) retVal = true; else retVal = false; delete[] checkFile; return retVal; } /** * @brief outputs debug information about the ResourceManager */ void ResourceManager::debug() const { PRINT(0)("=RM===================================\n"); PRINT(0)("= RESOURCE-MANAGER DEBUG INFORMATION =\n"); PRINT(0)("======================================\n"); // if it is not initialized PRINT(0)(" Reference is: %p\n", ResourceManager::singletonRef); PRINT(0)(" Data-Directory is: %s\n", this->dataDir); PRINT(0)(" List of Image-Directories: "); std::vector::const_iterator imageDir; for (imageDir = this->imageDirs.begin(); imageDir != this->imageDirs.end(); imageDir++) PRINT(0)("%s ", (*imageDir)); PRINT(0)("\n"); PRINT(0)("List of all stored Resources:\n"); std::vector::const_iterator resource; for (resource = this->resourceList.begin(); resource != this->resourceList.end(); resource++) { PRINT(0)("-----------------------------------------\n"); PRINT(0)("Name: %s; References: %d; Type: %s ", (*resource)->name, (*resource)->count, ResourceManager::ResourceTypeToChar((*resource)->type)); PRINT(0)("gets deleted at "); switch((*resource)->prio) { default: case RP_NO: PRINT(0)("first posibility (0)\n"); break; case RP_LEVEL: PRINT(0)("the end of the Level (1)\n"); break; case RP_CAMPAIGN: PRINT(0)("the end of the campaign (2)\n"); break; case RP_GAME: PRINT(0)("when leaving the game (3)\n"); break; } } PRINT(0)("==================================RM==\n"); } /** * @brief converts a ResourceType into the corresponding String * @param type the ResourceType to translate * @returns the converted String. */ const char* ResourceManager::ResourceTypeToChar(ResourceType type) { return ResourceManager::resourceNames[type]; } /** * @brief converts a String into a ResourceType (good for loading) * @param resourceType the name of the Type * @returns the Number of the Type, or 0 (defautl) if not found. */ ResourceType ResourceManager::stringToResourceType(const char* resourceType) { assert(resourceType != NULL); for (unsigned int i = 0; i < RESOURCE_TYPE_SIZE; i++) if (!strcmp(resourceType, ResourceManager::resourceNames[i])) return (ResourceType)i; return (ResourceType)0; } /** * The Names of the ResourceTypes */ const char* ResourceManager::resourceNames[] = { #ifndef NO_MODEL "ObjectModel", "PrimitiveModel", "MD2-Data", #endif #ifndef NO_TEXT "Font", #endif #ifndef NO_AUDIO "Wav", "mp3", "ogg", #endif #ifndef NO_TEXTURES "Texture", #endif #ifndef NO_SHADERS "Shader", #endif };