2019-11-24 23:15:56 +08:00
|
|
|
#include "SpineSkeletonDataCache.h"
|
|
|
|
|
2020-11-04 19:09:30 +08:00
|
|
|
#if !defined(CC_USE_SPINE_CPP) || CC_USE_SPINE_CPP
|
2019-11-30 01:32:12 +08:00
|
|
|
SpineSkeletonDataCache* SpineSkeletonDataCache::getInstance()
|
|
|
|
{
|
|
|
|
static SpineSkeletonDataCache internalShared;
|
|
|
|
return &internalShared;
|
2019-11-24 23:15:56 +08:00
|
|
|
}
|
|
|
|
|
2019-11-30 01:32:12 +08:00
|
|
|
SpineSkeletonDataCache::SpineSkeletonDataCache()
|
2019-11-24 23:15:56 +08:00
|
|
|
{
|
2019-11-30 01:32:12 +08:00
|
|
|
_reportError = &cocos2d::log;
|
2019-11-24 23:15:56 +08:00
|
|
|
}
|
|
|
|
|
2019-11-30 01:32:12 +08:00
|
|
|
void SpineSkeletonDataCache::setErrorReportFunc(void(*errorfunc)(const char* pszFormat, ...))
|
2019-11-24 23:15:56 +08:00
|
|
|
{
|
2019-11-30 01:32:12 +08:00
|
|
|
_reportError = std::move(errorfunc);
|
2019-11-24 23:15:56 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2019-12-12 23:24:50 +08:00
|
|
|
spine::SkeletonData* skeletonData = nullptr;
|
|
|
|
spine::AttachmentLoader* loader = nullptr;
|
2019-11-24 23:15:56 +08:00
|
|
|
bool ok = false;
|
|
|
|
|
|
|
|
auto fileExtension = cocos2d::FileUtils::getInstance()->getFileExtension(dataFile);
|
|
|
|
|
2019-12-12 23:24:50 +08:00
|
|
|
static spine::Cocos2dTextureLoader s_textureLoader;
|
|
|
|
|
2019-11-24 23:15:56 +08:00
|
|
|
do {
|
2019-12-12 23:24:50 +08:00
|
|
|
auto atlas = new (__FILE__, __LINE__) spine::Atlas(atlasFile, &s_textureLoader);
|
2019-11-24 23:15:56 +08:00
|
|
|
|
|
|
|
if (nullptr == (atlas))
|
|
|
|
break;
|
|
|
|
|
2019-12-12 23:24:50 +08:00
|
|
|
loader = new (__FILE__, __LINE__) spine::Cocos2dAtlasAttachmentLoader(atlas);
|
2019-11-24 23:15:56 +08:00
|
|
|
|
|
|
|
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") {
|
2019-12-12 23:24:50 +08:00
|
|
|
/*auto binary = new (__FILE__, __LINE__) spine::SkeletonBinary(loader);
|
2019-11-24 23:15:56 +08:00
|
|
|
if (nullptr == binary) {
|
2019-12-12 23:24:50 +08:00
|
|
|
delete (atlas);
|
2019-11-24 23:15:56 +08:00
|
|
|
break;
|
2019-12-12 23:24:50 +08:00
|
|
|
}*/
|
|
|
|
spine::SkeletonBinary binary(loader);
|
2019-11-24 23:15:56 +08:00
|
|
|
|
2019-12-12 23:24:50 +08:00
|
|
|
binary.setScale(scale);
|
|
|
|
skeletonData = binary.readSkeletonDataFile(dataFile); // spSkeletonBinary_readSkeletonDataFile(binary, dataFile);
|
|
|
|
if ((!binary.getError().isEmpty())) {
|
2019-11-24 23:15:56 +08:00
|
|
|
++failed;
|
2019-12-12 23:24:50 +08:00
|
|
|
_reportError("#parse spine .skel data file failed, error:%s", binary.getError().buffer());
|
2019-11-24 23:15:56 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
2019-12-12 23:24:50 +08:00
|
|
|
spine::SkeletonJson json(loader);
|
2019-11-24 23:15:56 +08:00
|
|
|
|
2019-12-12 23:24:50 +08:00
|
|
|
json.setScale(scale);
|
|
|
|
skeletonData = json.readSkeletonDataFile(dataFile);
|
|
|
|
if ((!json.getError().isEmpty())) {
|
2019-11-24 23:15:56 +08:00
|
|
|
++failed;
|
2019-12-12 23:24:50 +08:00
|
|
|
_reportError("#parse spine .json data file failed, error:%s", json.getError().buffer());
|
2019-11-24 23:15:56 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-12-12 23:24:50 +08:00
|
|
|
/*if ((loader->error1 != nullptr)) {
|
2019-11-24 23:15:56 +08:00
|
|
|
++failed;
|
2019-11-30 01:32:12 +08:00
|
|
|
_reportError("#parse spine attachment failed, error:%s%s", loader->error1, loader->error2);
|
2019-12-12 23:24:50 +08:00
|
|
|
}*/
|
2019-11-24 23:15:56 +08:00
|
|
|
|
|
|
|
if (failed > 0) {
|
|
|
|
if (skeletonData != nullptr)
|
2019-12-12 23:24:50 +08:00
|
|
|
delete (skeletonData);
|
2019-11-24 23:15:56 +08:00
|
|
|
|
2019-12-12 23:24:50 +08:00
|
|
|
delete (atlas);
|
|
|
|
delete (loader);
|
2019-11-24 23:15:56 +08:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
2020-11-04 19:09:30 +08:00
|
|
|
|
|
|
|
#else
|
|
|
|
|
|
|
|
SpineSkeletonDataCache* SpineSkeletonDataCache::getInstance()
|
|
|
|
{
|
|
|
|
static SpineSkeletonDataCache internalShared;
|
|
|
|
return &internalShared;
|
|
|
|
}
|
|
|
|
|
|
|
|
SpineSkeletonDataCache::SpineSkeletonDataCache()
|
|
|
|
{
|
|
|
|
_reportError = &cocos2d::log;
|
|
|
|
}
|
|
|
|
|
|
|
|
void SpineSkeletonDataCache::setErrorReportFunc(void(*errorfunc)(const char* pszFormat, ...))
|
|
|
|
{
|
|
|
|
_reportError = errorfunc;
|
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
|
|
_reportError("#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;
|
|
|
|
_reportError("#parse spine .json data file failed, error:%s", json->error);
|
|
|
|
}
|
|
|
|
|
|
|
|
spSkeletonJson_dispose(json);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((loader->error1 != nullptr)) {
|
|
|
|
++failed;
|
|
|
|
_reportError("#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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|