/* 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: ... */ #define DEBUG_SPECIAL_MODULE DEBUG_MODULE_LOAD #include "resource.h" #include "resource_manager.h" #include "debug.h" namespace Resources { //! Define an ObjectList for the Resources ObjectListDefinition(Resource); /** * @brief standard constructor * @param type the Type this resource belongs to. */ Resource::Resource (Type* type) : _pointer(NULL), _type(type) { this->registerObject(this, Resource::_objectList); } /** * @brief standard deconstructor */ Resource::~Resource () { // delete what has to be deleted here } /** * @brief Locates a File inside of the Resources Paths and returns the appended path. * * @param fileName the Name of the file to look for. * @returns the Name of the File prepended with the PAth it is in, if found, empty String ("") otherwise. * * This Function searches in (ordered): * 1. mainGlobalPath (from ResourceManger) * 2. all of the global Paths (from ResourceManger) * 3. all of the Resources Paths (from Resources::Type) * * in each of these directory, first "./" is searched, and afterwards all of the subDirs (from Resources::Type) are searched. * * @todo finish it!! */ std::string Resource::locateFile(const std::string& fileName) const { if ((ResourceManager::getInstance()->mainGlobalPath() + File(fileName)).exists() ) return (ResourceManager::getInstance()->mainGlobalPath() + File(fileName)).name(); std::string locatedFile; locatedFile = locateFileInSubDir(ResourceManager::getInstance()->mainGlobalPath(), fileName); if (!locatedFile.empty()) { return locatedFile; } if (File(fileName).exists()) return fileName; return (ResourceManager::getInstance()->mainGlobalPath() + File(fileName)).name(); } /** * @brief tests in all the SubDirectories defined in Resource under Directory if the fileName exists. * @param directory the directory to in what to search for all subdirectories for. * @param fileName the Name of the File to query for * @return true on success. */ std::string Resource::locateFileInSubDir(const Directory& directory, const std::string& fileName) const { std::vector::const_iterator it; for (it = this->_type->resourceSubPaths().begin(); it != this->_type->resourceSubPaths().end(); ++it) { Directory dir = directory + (*it); File file = dir + File(fileName); if ((dir+ File(fileName)).exists()) return (dir+File(fileName)).name(); } return ""; } /** * @param loadString the Identifier of the Resource. * @returns a Store-Pointer to the Resource if found, NULL otherwise */ StorePointer* Resource::acquireResource(const std::string& loadString) { //const Type* const type = _resourceTypes[this->_type->id()]; for (unsigned int i = 0; i < _type->storedResources().size(); ++i) { if (_type->storedResources()[i]->loadString() == loadString) return _type->storedResources()[i]; } return NULL; } /** * @brief registers a StorePointer to a Resource's Type. * @param pointer the StorePointer to register. */ void Resource::addResource(StorePointer* pointer) { assert(pointer != NULL); this->_type->addResource(pointer); } /////////////////// //// KEEPLEVEL //// /////////////////// //! Constructs a default KeepLevel as Set in the ResourceManager via setDefaultKeepLevel. KeepLevel::KeepLevel() { this->_keepLevel = ResourceManager::getInstance()->defaultKeepLevel().keepLevel(); } /** * @param keepLevel the level to set. */ KeepLevel::KeepLevel(unsigned int keepLevel) { _keepLevel = keepLevel; } /** * @brief constructor of a KeepLevel. * @param keepLevelName the Name of the KeepLevel. Must be one Name of the defined Names in the ResourceManager. * * @note the Name is transformed into an Integer for fast interpretation. */ KeepLevel::KeepLevel(const std::string& keepLevelName) { this->_keepLevel = ResourceManager::getInstance()->getKeepLevelID(keepLevelName); } /** * @returns the name of the KeepLevel. */ const std::string& KeepLevel::name() const { return ResourceManager::getInstance()->getKeepLevelName(this->_keepLevel); } /////////////////////// //// STORE POINTER //// /////////////////////// /** * @brief allocates a StorePointer. * @param loadString An identifier String that is unique between all resources of this type. * @param keepLevel the KeepLevel at wich to keep this resource. */ StorePointer::StorePointer(const std::string& loadString, const KeepLevel& keeplevel) : _loadString(loadString), _keepLevel(keeplevel) { PRINTF(4)("Acquired a Resource with LoadString '%s' and KeepLevel '%s'\n", _loadString.c_str(), _keepLevel.name().c_str()); } StorePointer::~StorePointer() { PRINTF(4)("Deleting Stored Resource '%s' from KeepLevel '%s'\n", _loadString.c_str(), _keepLevel.name().c_str()); }; ////////////// //// TYPE //// ////////////// /** * @brief allocates a Type. * @param typeName the Name of the Type to be stored in this Container. */ Type::Type(const std::string& typeName) : _typeName(typeName) { ResourceManager::getInstance()->registerType(this); PRINTF(4)("Created ResourceType '%s'\n", typeName.c_str()); } //! Destructs a Type. Type::~Type() { ResourceManager::getInstance()->unregisterType(this); } /** * @brief adds a Resource to this Resource's type. * @param resource the Resource to add. */ void Type::addResource(StorePointer* resource) { this->_storedResources.push_back(resource); } /** * @brief adds a Path to the Type's resource-paths. * @param path the path-name to add. */ bool Type::addResourcePath(const std::string& path) { std::vector::const_iterator it; for (it = this->_resourcePaths.begin(); it != this->_resourcePaths.end(); ++it) if ((*it) == path) return false; this->_resourcePaths.push_back(path); return true; } /** * @brief Adds a SubPath to the Type's resource-subpaths. * @param subPath the subpath to add. */ bool Type::addResourceSubPath(const std::string& subPath) { std::vector::const_iterator it; for (it = this->_resourceSubPaths.begin(); it != this->_resourceSubPaths.end(); ++it) if ((*it) == subPath) return false; this->_resourceSubPaths.push_back(subPath); return true; } /** * @brief Unloads all Resources below a certain Level. * @param keepLevel the KeepLevel at what to remove the Resources from. */ void Type::unloadAllBelowKeepLevel(const Resources::KeepLevel& keepLevel) { std::vector::iterator it, it2; bool finished = false; while (!finished) { finished = true; for (it = this->_storedResources.begin(); it != this->_storedResources.end();++it) if((*it)->keepLevel() < keepLevel && (*it)->last()) { delete (*it); this->_storedResources.erase(it); finished = false; break; } } } /** * @brief print out some nice Debug information in a beatifully designed style */ void Type::debug() const { PRINT(0)(" ResourceType '%s' stores %d Resources\n", this->_typeName.c_str(), this->_storedResources.size()); PRINT(0)(" Paths:\n"); for (unsigned int i = 0; i < this->_resourcePaths.size(); ++i) PRINT(0)(" %s\n", this->_resourcePaths[i].name().c_str()); PRINT(0)(" Sub-Paths:"); for (unsigned int i = 0; i < this->_resourceSubPaths.size(); ++i) PRINT(0)(" '%s'", this->_resourceSubPaths[i].name().c_str()); PRINT(0)("\n"); PRINT(0)(" Loaded Resources:\n"); std::vector::const_iterator it; for (it = this->_storedResources.begin(); it != this->_storedResources.end(); ++it) PRINT(0)(" '%s' : KeepLevel '%s'\n", (*it)->loadString().c_str(), (*it)->keepLevel().name().c_str()); } }