/* 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 "debug.h" #include #include namespace Resources { /// Definition of the ResourceManager's ObjectList. ObjectListDefinition(ResourceManager); //! Singleton Reference to the ResourceManager ResourceManager* ResourceManager::_singletonRef = NULL; /** * @brief standard constructor */ ResourceManager::ResourceManager () : _defaultKeepLevel(0) { this->registerObject(this, ResourceManager::_objectList); this->setName("ResourceManager"); this->_mainGlobalPath = Directory("./"); } /** * @brief standard destructor */ ResourceManager::~ResourceManager () { this->unloadAllBelowKeepLevel(this->_keepLevelNames.size()); ResourceManager::_singletonRef = NULL; } /** * @brief Registers a new Type to the ResourceManager. * @param type the Type to register. */ void ResourceManager::registerType(Resources::Type* type) { this->_resourceTypes.push_back(type); PRINTF(5)("ResourceType '%s' added\n", type->storedClassName().c_str()); } /** * @brief Unregisters a new Type to the ResourceManager. * @param type the Type to unregister. */ void ResourceManager::unregisterType(Resources::Type* type) { std::vector::iterator it = std::find (this->_resourceTypes.begin(), this->_resourceTypes.end(), type); if (it != this->_resourceTypes.end()) { this->_resourceTypes.erase(it); PRINTF(5)("ResourceType '%s' removed\n", type->storedClassName().c_str()); } } /** * @brief Sets the main Global path (the main path Resources are searched for) * @param directory the directory to set. * @see Resource::locateFile */ void ResourceManager::setMainGlobalPath(const Directory& directory) { this->_mainGlobalPath = directory; this->_mainGlobalPath.open(); } /** * @brief add a Global search path. (global paths besided the main path.) * @param directory a directory to add. */ void ResourceManager::addGlobalPath(const Directory& directory) { std::vector::const_iterator it = std::find(this->_globalPaths.begin(), this->_globalPaths.end(), directory); if (it == this->_globalPaths.end()) this->_globalPaths.push_back(directory); } /** * @brief add a ResourcePath to a Type's Paths. * @param resourceName the Type's name of Resource to add the path to. * @param pathName pathName the Name of the path to add. * @return true on success. (if a path was added (no duplicate, and resourceName existed). */ bool ResourceManager::addResourcePath(const std::string& resourceName, const std::string& pathName) { std::vector::iterator it; for (it = this->_resourceTypes.begin(); it != this->_resourceTypes.end(); ++it) if (*(*it) == resourceName) return (*it)->addResourcePath(pathName); PRINTF(2)("ResourcePath %s could not be added to the ResourceType %s\n", pathName.c_str(), resourceName.c_str()); return false; } /** * @brief add a ResourcePath to a Type's SubPaths. * @param resourceName the Type's name of Resource to add the subpath to. * @param pathName pathName the Name of the path to add. * @return true on success. (if a path was added (no duplicate, and resourceName existed). */ bool ResourceManager::addResourceSubPath(const std::string& resourceName, const std::string& pathName) { std::vector::iterator it; for (it = this->_resourceTypes.begin(); it != this->_resourceTypes.end(); ++it) if (*(*it) == resourceName) return (*it)->addResourceSubPath(pathName); PRINTF(2)("ResourceSubPath %s could not be added to the ResourceType %s\n", pathName.c_str(), resourceName.c_str()); return false; } /** * @brief checks wether a File is inside of the MainPath. * @param fileInside the file to check * @return true if the file is inside. */ bool ResourceManager::checkFileInMainPath(const File& fileInside) { return (this->_mainGlobalPath + fileInside).exists(); } /** * @brief prepends the fileName by the MainGlobalPath (same as mainGlobalPath + '/' + fileName). * @param fileName The FileName to prepend * @returns the prepended file-name */ std::string ResourceManager::prependAbsoluteMainPath(const std::string& fileName) { return (this->_mainGlobalPath + File(fileName)).name(); } /** * @brief add a KeepLevelName (this function just counts upwards). * @param keepLevelName the Name of the KeepLevel to set. * @returns the Level the Name was set to. */ unsigned int ResourceManager::addKeepLevelName(const std::string& keepLevelName) { this->_keepLevelNames.push_back(keepLevelName); return _keepLevelNames.size()-1; } /** * @param keepLevelName the Name of the KeepLevel. * @returns the ID of the KeepLevel named keepLevelName */ unsigned int ResourceManager::getKeepLevelID(const std::string& keepLevelName) const { for (unsigned int i = 0; i < this->_keepLevelNames.size(); ++i) if (this->_keepLevelNames[i] == keepLevelName) return i; PRINTF(2)("KeepLevel '%s' not found. Using 0 instead\n", keepLevelName.c_str()); return 0; } /** * @param keepLevelID the ID to check. * @return the name of the KeepLevel. */ const std::string& ResourceManager::getKeepLevelName(unsigned int keepLevelID) const { assert(keepLevelID < this->_keepLevelNames.size()); return this->_keepLevelNames[keepLevelID]; } /** * @brief loads a Resource from a TypeName and a loadString. * @param resourceTypeName The Name of the Type to what to load a Resource from. * @param loadString the loadString to load in the Type. */ void ResourceManager::loadFromLoadString(const std::string& resourceTypeName, const std::string& loadString, const KeepLevel& keepLevel) { std::vector::const_iterator it; for (it = this->_resourceTypes.begin(); it != this->_resourceTypes.end(); ++it) { if (*(*it) == resourceTypeName) { (*it)->createFromString(loadString, keepLevel); /// TODO check if the resource was allocated!! return ; } } return ; } /** * @brief unloads all Resources below a certain threshhold. * @param keepLevel the KeepLevel below which to erase. * * @not Resources will only be erased, if th keepLevel is below, and the resources are not * referenced anymore. */ void ResourceManager::unloadAllBelowKeepLevel(const Resources::KeepLevel& keepLevel) { std::vector::const_iterator it; for (it = this->_resourceTypes.begin(); it != this->_resourceTypes.end(); ++it) { (*it)->unloadAllBelowKeepLevel(keepLevel); } } /** * @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"); PRINT(0)(" MainGlobal search path is %s\n", this->_mainGlobalPath.name().c_str()); if(!this->_globalPaths.empty()) { PRINT(0)(" Additional Global search Paths are: "); for (unsigned int i = 0; i < this->_globalPaths.size(); ++i) PRINT(0)("'%s' ", this->_globalPaths[i].name().c_str()); PRINT(0)("\n"); } PRINT(0)(" Listing %d Types: \n", this->_resourceTypes.size()); std::vector::const_iterator it; for (it = this->_resourceTypes.begin(); it != this->_resourceTypes.end(); ++it) { (*it)->debug(); if (it != --this->_resourceTypes.end()) PRINT(0)(" ------------------------------------\n "); } PRINT(0)("KeepLevels are: "); for (unsigned int i = 0; i < this->_keepLevelNames.size(); ++i) PRINT(0)("%d:'%s' ", i, this->_keepLevelNames[i].c_str()); PRINT(0)("\n"); PRINT(0)("=================================RM==/\n"); } }