SpriteFrameCache
SpriteFrameCache::getInstance()->addSpriteFramesWithFile(""); 复制代码
TextureCache
std::unordered_map<std::string, TexInfo*> _textures; 复制代码
key的来源
Texture2D * TextureCache::addImage(const std::string &path){ std::string fullpath = GetFullPath(path); auto it = _textures.find(fullpath); } std::string GetFullPath(std::string path){ std::string fullPath = FileUtils::getInstance()->fullPathForFilename(path); if (fullPath.length() > 0){ return fullPath; }else{ return path; } } std::string FileUtils::fullPathForFilename(const std::string &filename) const { if (path[0] == '/') { return filename; } std::string name = filename; int index = name.find("/../"); while (index > 0) { int last = name.find_last_of("/", index-1); if (last > 0) { name = name.substr(0, last) + name.substr(index+3, name.length()); } else { break; } index = name.find("/../"); } // Already Cached ? auto cacheIter = _fullPathCache.find(name); // 又一个很重要的cache: mutable std::unordered_map<std::string, std::string> _fullPathCache; if(cacheIter != _fullPathCache.end()) { return cacheIter->second; } // Get the new file name. const std::string newFilename(getNewFilename(name)); std::string fullpath; for (const auto& searchIt : _searchPathArray){ for (const auto& resolutionIt : _searchResolutionsOrderArray){ fullpath = this->getPathForFilename(newFilename, resolutionIt, searchIt); if (!fullpath.empty()){ // Using the filename passed in as key. _fullPathCache.emplace(name, fullpath); return fullpath; } } } return ""; } 复制代码
测试结果
网络异常,图片无法展示
|
- name为
ani1/test.png
,在textureCache中的映射key为res/ani1/test.png
- name为
res/ani1/test.png
,在textureCache中的映射key为exePath/res/ani1/test.png
相当于加载的是磁盘的同一份图片,结果却产生了2个纹理,理想情况是产生1份,产生这个问题的原因是:
TextureCache的key受filePathCache的影响,而filePathCache受searchPath的影响
searchPath的目录的顺序为:
- exePath
- src
- res
ani1/test.png
只能在res目录下找到,res/ani1/test.png
只能在exePath目录下找到,所以最终2者的key是完全不同的。
造成这个问题是因为我设置了一个无效的searchPath,而在win32平台判断文件是否存在发生了异常
bool FileUtilsWin32::isFileExistInternal(const std::string& strFilePath) const { if (strFilePath.empty()) { return false; } std::string strPath = strFilePath; if (!isAbsolutePath(strPath)) { // Not absolute path, add the default root path at the beginning. strPath.insert(0, _defaultResRootPath); } DWORD attr = GetFileAttributesW(StringUtf8ToWideChar(strPath).c_str()); if(attr == INVALID_FILE_ATTRIBUTES || (attr & FILE_ATTRIBUTE_DIRECTORY)) return false; // not a file return true; } 复制代码
当strFile为res/ani1/test.png
返回的是FILE_ATTRIBUTE_ARCHIVE
,isFileExistInternal
直接返回了true,认为存在,准确说这个文件是相对于exe是存在的,但是这个路径不是完整路径
- 测试代码:
char* file = "res/ani2/test.png"; // exe运行目录下真的有这个文件 //file = "c://a/1.png"; DWORD attr = GetFileAttributesW(StringUtf8ToWideChar(file).c_str()); if (attr == INVALID_FILE_ATTRIBUTES || (attr & FILE_ATTRIBUTE_DIRECTORY)) { cocos2d::log("file not exist"); } else{ cocos2d::log("file exist"); } 复制代码
为什么会出现search paths异常
FileUtils::getInstance()->addSearchPath("res"); void FileUtils::addSearchPath(const std::string &searchpath,const bool front) { if (!isAbsolutePath(searchpath)) prefix = _defaultResRootPath; } 复制代码
当添加searchPaths的时候,如果是相对路径,则会追加_defaultResRootPath
,而_defaultResRootPath
在win32上的来源是ProjectConfig
,在SimulatorWin::run
中就会从命令行参数中解析workdir
最终传递给_defaultResRootPath
void FileUtils::setDefaultResourceRootPath(const std::string& path) { // 最主要的原因是这里缺少对path的校验 if (_defaultResRootPath != path) { _fullPathCache.clear(); _defaultResRootPath = path; if (!_defaultResRootPath.empty() && _defaultResRootPath[_defaultResRootPath.length()-1] != '/') { _defaultResRootPath += '/'; } // Updates search paths setSearchPaths(_originalSearchPaths); } } 复制代码
release出现问题就是因为args中缺少workdir
网络异常,图片无法展示
|
结论
SearchPath的影响还是非常大的,写资源路径的时候,最好统一相对于一个目录写,不然cache中容易出现多份相同的资源。