cocos2dx 3.6源码分析之文件路径

cocos2dx中资源文件都放在Resources目录中,编译后会自动复制到exe所在的目录中。

核心类是FileUtils类,一个单例类。

三个重要的函数

void addSearchPath(const std::string & path, const bool front=false);
virtual void addSearchResolutionsOrder(const std::string &order,const bool front=false);
virtual std::string fullPathForFilename(const std::string &filename) const;

依次分析。

void FileUtils::addSearchPath(const std::string &searchpath,const bool front)
{
    std::string prefix;
    if (!isAbsolutePath(searchpath))
        prefix = _defaultResRootPath;

    std::string path = prefix + searchpath;
    if (path.length() > 0 && path[path.length()-1] != '/')
    {
        path += "/";
    }
    if (front) {
        _searchPathArray.insert(_searchPathArray.begin(), path);
    } else {
        _searchPathArray.push_back(path);
    }
}

核心数据成员_searchPathArray,首先判断是否是绝对路径,如果不是则通过平台相关的默认资源根路径得到前缀prefix。其次判断给定的字符串后有没有/,没有则加上。

第二个参数font代表搜索优先级,有优先级则插入到_searchPathArray的前端,否则放入后面。vector用Insert感觉还挺奇怪的。

void FileUtils::addSearchResolutionsOrder(const std::string &order,const bool front)
{
    std::string resOrder = order;
    if (!resOrder.empty() && resOrder[resOrder.length()-1] != '/')
        resOrder.append("/");
    
    if (front) {
        _searchResolutionsOrderArray.insert(_searchResolutionsOrderArray.begin(), resOrder);
    } else {
        _searchResolutionsOrderArray.push_back(resOrder);
    }
}

核心数据成员_searchResolutionsOrderArray,这里我理解为子目录,Resolutions这命名用在这里让我十分费解。同样如果传入字符串尾部没有/则加/。如果有优先级顺序则加入都头部,否则尾部。

下面就是重头戏了,查找路径的时候如何拼接目录和子目录为一个字符串。

std::string FileUtils::fullPathForFilename(const std::string &filename) const
{
    if (filename.empty())
    {
        return "";
    }
    
    if (isAbsolutePath(filename))
    {
        return filename;
    }

    // Already Cached ?
    auto cacheIter = _fullPathCache.find(filename);
    if(cacheIter != _fullPathCache.end())
    {
        return cacheIter->second;
    }
    
    // Get the new file name.
    const std::string newFilename( getNewFilename(filename) );
    
    std::string fullpath;
    
    for (const auto& searchIt : _searchPathArray)
    {
        for (const auto& resolutionIt : _searchResolutionsOrderArray)
        {
            fullpath = this->getPathForFilename(newFilename, resolutionIt, searchIt);
            
            if (fullpath.length() > 0)
            {
                // Using the filename passed in as key.
                _fullPathCache.insert(std::make_pair(filename, fullpath));
                return fullpath;
            }
            
        }
    }
    
    if(isPopupNotify()){
        CCLOG("cocos2d: fullPathForFilename: No file found at %s. Possible missing file.", filename.c_str());
    }

    // The file wasn't found, return empty string.
    return "";
}

这段代码思路,就是传入一个文件名,如何在资源路径中找到绝对路径的全名出来。这里就要用到之前的搜索路径和子路径了。

首先判断是否为空和是否为绝对路径,以"/"开头被认为是绝对路径则直接返回。然后再看有没有再文件缓存里面如果有则直接返回。

如果都没有则开始拼接一个新的绝对路径出来。这里就用到了前面添加的2个重要的数据成员_searchPathArray和_searchResolutionsOrderArray。

首先对_searchPathArray进行遍历,在每一个_searchPathArray成员中再对_searchResolutionsOrderArray进行遍历。

然后进入核心拼接函数。

std::string FileUtils::getPathForFilename(const std::string& filename, const std::string& resolutionDirectory, const std::string& searchPath) const
{
    std::string file = filename;
    std::string file_path = "";
    size_t pos = filename.find_last_of("/");
    if (pos != std::string::npos)
    {
        file_path = filename.substr(0, pos+1);
        file = filename.substr(pos+1);
    }
    
    // searchPath + file_path + resourceDirectory
    std::string path = searchPath;
    path += file_path;
    path += resolutionDirectory;
    
    path = getFullPathForDirectoryAndFilename(path, file);
    
    //CCLOG("getPathForFilename, fullPath = %s", path.c_str());
    return path;
}

找到最后一个"/"出现的位置,如果filename字符串中没有"/",则Path = searchPath + resolutionDirectory,这里path只是文件夹路径,所以searchPath和resolutionDirectory也可以是多级目录路径。

getFullPathForDirectoryAndFilename会把目录路径和文件路径拼接起来。最后得到一个完整的path。

 

 

  

posted @ 2015-08-11 16:56  超三界  阅读(2042)  评论(0编辑  收藏  举报