#include "SpineSkeletonDataCache.h" static auto error_log = &cocos2d::log; namespace spine { extern void(*onLoadTextureFailed)(const char* format, ...); } void SpineSkeletonDataCache::setErrorLogFunc(void(*errorfunc)(const char* pszFormat, ...)) { error_log = errorfunc; spine::onLoadTextureFailed = errorfunc; } SpineSkeletonDataCache* SpineSkeletonDataCache::getInstance() { static SpineSkeletonDataCache internalShared; return &internalShared; } void SpineSkeletonDataCache::removeData(const char* dataFile) { auto target = _cacheTable.find(dataFile); if (target != _cacheTable.end()) { target->second->release(); _cacheTable.erase(target); } } SpineSkeletonDataCache::SkeletonData* SpineSkeletonDataCache::addData(const char* dataFile, const char* atlasFile, float scale) { auto target = _cacheTable.find(dataFile); if (target != _cacheTable.end()) { return target->second; } spSkeletonData* skeletonData = nullptr; spAttachmentLoader* loader = nullptr; bool ok = false; auto fileExtension = cocos2d::FileUtils::getInstance()->getFileExtension(dataFile); do { spAtlas* atlas = spAtlas_createFromFile(atlasFile, 0); if (nullptr == (atlas)) break; loader = (spAttachmentLoader*)Cocos2dAttachmentLoader_create(atlas); int failed = 0; /* ** Atlas is used by shared attachment loader, temp json or binary should be dispose. ** Cache, we just need SkeletonData & atlas. */ if (fileExtension == ".skel") { auto binary = spSkeletonBinary_createWithLoader(loader); if (nullptr == binary) { spAtlas_dispose(atlas); break; } binary->scale = scale; skeletonData = spSkeletonBinary_readSkeletonDataFile(binary, dataFile); if ((binary->error != nullptr)) { ++failed; error_log("#parse spine .skel data file failed, error:%s", binary->error); } spSkeletonBinary_dispose(binary); } else { spSkeletonJson* json = spSkeletonJson_createWithLoader(loader); if (nullptr == json) { spAtlas_dispose(atlas); break; } json->scale = scale; skeletonData = spSkeletonJson_readSkeletonDataFile(json, dataFile); if ((json->error != nullptr)) { ++failed; error_log("#parse spine .json data file failed, error:%s", json->error); } spSkeletonJson_dispose(json); } if ((loader->error1 != nullptr)) { ++failed; error_log("#parse spine attachment failed, error:%s%s", loader->error1, loader->error2); } if (failed > 0) { if (skeletonData != nullptr) spSkeletonData_dispose(skeletonData); spAtlas_dispose(atlas); spAttachmentLoader_dispose(loader); break; } ok = true; } while (false); if (ok) { auto newData = new SkeletonData(skeletonData, loader); _cacheTable.emplace(dataFile, newData); return newData; } return nullptr; } void SpineSkeletonDataCache::removeAllData(void) { for (auto & e : _cacheTable) { e.second->release(); } _cacheTable.clear(); } void SpineSkeletonDataCache::removeAllUnusedData(void) { auto _First = _cacheTable.begin(); auto _Last = _cacheTable.end(); for (; _First != _Last; ) { if ((*_First).second->getReferenceCount() == 1) { (*_First).second->release(); _cacheTable.erase(_First++); continue; } ++_First; } }