function display.addSpriteFrames(plistFilename, image, handler)
local async = type(handler) == "function"
local asyncHandler = nil
if async then
asyncHandler = function()
local texture = sharedTextureCache:getTextureForKey(image)
assert(texture, string.format("The texture %s, %s is unavailable.", plistFilename, image))
sharedSpriteFrameCache:addSpriteFrames(plistFilename, texture)
handler(plistFilename, image)
end
end
if display.TEXTURES_PIXEL_FORMAT[image] then
cc.Texture2D:setDefaultAlphaPixelFormat(display.TEXTURES_PIXEL_FORMAT[image])
if async then
sharedTextureCache:addImageAsync(image, asyncHandler)
else
sharedSpriteFrameCache:addSpriteFrames(plistFilename, image)
end
cc.Texture2D:setDefaultAlphaPixelFormat(cc.TEXTURE2_D_PIXEL_FORMAT_RGB_A8888)
else
if async then
sharedTextureCache:addImageAsync(image, asyncHandler)
else
sharedSpriteFrameCache:addSpriteFrames(plistFilename, image)
end
end
end
导致原因:因为异步加载后会取出当前Texture2D::getDefaultAlphaPixelFormat()的格式,加载需要一定时间,当前格式就被更改了。当加载好的时候再去转换格式,就不能取到加载的时候的pixelformat了。。。处理把pixelformat 保存在异步加载中。然后加载好的时候不用取默认格式了。
修改 TextureCache.cpp 文件 有3处修改地方
第一处
AsyncStruct *data = new (std::nothrow) AsyncStruct(fullpath, callback)
修改成
AsyncStruct *data = new (std::nothrow) AsyncStruct(fullpath, callback, Texture2D::getDefaultAlphaPixelFormat())
void TextureCache::addImageAsync(const std::string &path, const std::function<void(Texture2D*)>& callback)
{
Texture2D *texture = nullptr;
std::string fullpath = FileUtils::getInstance()->fullPathForFilename(path);
auto it = _textures.find(fullpath);
if( it != _textures.end() )
texture = it->second;
if (texture != nullptr)
{
if (callback) callback(texture);
return;
}
// check if file exists
if ( fullpath.empty() || ! FileUtils::getInstance()->isFileExist( fullpath ) ) {
if (callback) callback(nullptr);
return;
}
// lazy init
if (_loadingThread == nullptr)
{
// create a new thread to load images
_loadingThread = new (std::nothrow) std::thread(&TextureCache::loadImage, this);
_needQuit = false;
}
if (0 == _asyncRefCount)
{
Director::getInstance()->getScheduler()->schedule(CC_SCHEDULE_SELECTOR(TextureCache::addImageAsyncCallBack), this, 0, false);
}
++_asyncRefCount;
// generate async struct
/* 异步加载设置纹理格式 */
AsyncStruct *data = new (std::nothrow) AsyncStruct(fullpath, callback, Texture2D::getDefaultAlphaPixelFormat());
//AsyncStruct *data = new (std::nothrow) AsyncStruct(fullpath, callback);
// add async struct into queue
_asyncStructQueue.push_back(data);
_requestMutex.lock();
_requestQueue.push_back(data);
_requestMutex.unlock();
_sleepCondition.notify_one();
}
第二处
texture->initWithImage(image)
修改成
texture->initWithImage(image, asyncStruct->format)
void TextureCache::addImageAsyncCallBack(float dt)
{
Texture2D *texture = nullptr;
AsyncStruct *asyncStruct = nullptr;
while (true)
{
// pop an AsyncStruct from response queue
_responseMutex.lock();
if(_responseQueue.empty())
{
asyncStruct = nullptr;
}else
{
asyncStruct = _responseQueue.front();
_responseQueue.pop_front();
// the asyncStruct's sequence order in _asyncStructQueue must equal to the order in _responseQueue
CC_ASSERT(asyncStruct == _asyncStructQueue.front());
_asyncStructQueue.pop_front();
}
_responseMutex.unlock();
if (nullptr == asyncStruct) {
break;
}
// check the image has been convert to texture or not
auto it = _textures.find(asyncStruct->filename);
if(it != _textures.end())
{
texture = it->second;
}
else
{
// convert image to texture
if (asyncStruct->loadSuccess)
{
Image* image = &(asyncStruct->image);
// generate texture in render thread
texture = new (std::nothrow) Texture2D();
/* 异步加载设置纹理格式 */
texture->initWithImage(image, asyncStruct->format);
//texture->initWithImage(image);
//parse 9-patch info
this->parseNinePatchImage(image, texture, asyncStruct->filename);
#if CC_ENABLE_CACHE_TEXTURE_DATA
// cache the texture file name
VolatileTextureMgr::addImageTexture(texture, asyncStruct->filename);
#endif
// cache the texture. retain it, since it is added in the map
_textures.insert( std::make_pair(asyncStruct->filename, texture) );
texture->retain();
texture->autorelease();
} else {
texture = nullptr;
CCLOG("cocos2d: failed to call TextureCache::addImageAsync(%s)", asyncStruct->filename.c_str());
}
}
// call callback function
if (asyncStruct->callback)
{
(asyncStruct->callback)(texture);
}
// release the asyncStruct
delete asyncStruct;
--_asyncRefCount;
}
if (0 == _asyncRefCount)
{
Director::getInstance()->getScheduler()->unschedule(CC_SCHEDULE_SELECTOR(TextureCache::addImageAsyncCallBack), this);
}
}
第三处
struct TextureCache::AsyncStruct
{
public:
AsyncStruct(const std::string& fn, std::function<void(Texture2D*)> f) : filename(fn), callback(f), loadSuccess(false) {}
std::string filename;
std::function<void(Texture2D*)> callback;
Image image;
bool loadSuccess;
};
修改成
struct TextureCache::AsyncStruct
{
public:
AsyncStruct(const std::string& fn, std::function<void(Texture2D*)> f, Texture2D::PixelFormat ft) : filename(fn), callback(f), format(ft), loadSuccess(false) {}
std::string filename;
std::function<void(Texture2D*)> callback;
Image image;
Texture2D::PixelFormat format;
bool loadSuccess;
};