cocos2d-x3.7 cclabel文字破碎,异常,变乱
效果图如下: 原因:在3.x中使用ttfconfig创建的label,为了性能是创建了缓存的,字体纹理缓存的大小默认是512*512(不同版本大小可能不一样) //CCFontAtlas.cpp
const int FontAtlas::CacheTextureWidth = 512;
const int FontAtlas::CacheTextureHeight = 512;
v3.7的label继承于batchnode: void Label::setFontAtlas(FontAtlas* atlas,bool distanceFieldEnabled /* = false */,bool useA8Shader /* = false */)
{
if (atlas == _fontAtlas)
{
FontAtlasCache::releaseFontAtlas(atlas);
return;
}
if (_fontAtlas)
{
FontAtlasCache::releaseFontAtlas(_fontAtlas);
_fontAtlas = nullptr;
}
_fontAtlas = atlas;
if (_textureAtlas)
{
//这里重置了_batchNodes的第一个元素的问题,也就是cclabel自己,
//那么如果之前缓存了多个纹理,即_batchNodes.size>1,
//其他的纹理就还没有被释放!!!
_textureAtlas->setTexture(_fontAtlas->getTexture(0));
}
else
{
SpriteBatchNode::initWithTexture(_fontAtlas->getTexture(0),30);
}
//...
}
再来看一下_batchNodes添加新的缓存纹理相应的代码: void Label::alignText()
{
if (_fontAtlas == nullptr || _currentUTF16String.empty())
{
setContentSize(Size::ZERO);
return;
}
_fontAtlas->prepareLetterDefinitions(_currentUTF16String);
auto& textures = _fontAtlas->getTextures();
//如果上面旧的缓存一直没有释放,
//那么当新的字体纹理缓存创建第二个时,不会被更新!!!
//所以你看到的文字就是错乱的!
if (textures.size() > _batchNodes.size())
{
for (auto index = _batchNodes.size(); index < textures.size(); ++index)
{
auto batchNode = SpriteBatchNode::createWithTexture(textures.at(index));
batchNode->setAnchorPoint(Vec2::ANCHOR_TOP_LEFT);
batchNode->setPosition(Vec2::ZERO);
Node::addChild(batchNode,0,Node::INVALID_TAG);
_batchNodes.push_back(batchNode);
}
}
//.......
}
根据上面的分析,其实可以发现,出现的这个bug的概率是很小的: 解决方案:因为更换字体、更改字体大小等,都会更换新的纹理(setFontAtlas),那么我们只用在该函数中重置_batchNodes即可: void Label::setFontAtlas(FontAtlas* atlas,bool useA8Shader /* = false */)
{
if (atlas == _fontAtlas)
{
FontAtlasCache::releaseFontAtlas(atlas);
return;
}
if (_fontAtlas)
{
FontAtlasCache::releaseFontAtlas(_fontAtlas);
_fontAtlas = nullptr;
}
_fontAtlas = atlas;
if (_textureAtlas)
{
_textureAtlas->setTexture(_fontAtlas->getTexture(0));
}
else
{
SpriteBatchNode::initWithTexture(_fontAtlas->getTexture(0),30);
}
//issue: text disorder
_batchNodes.clear();
_batchNodes.push_back(this);
//...
}
v3.10github上已经有3.10的代码,看了一下cclabel,已经重构了,label不再继承BatchNode class CC_DLL Label : public Node,public LabelProtocol,public BlendProtocol
而每一个文字使用: void Label::setFontAtlas(FontAtlas* atlas,bool useA8Shader /* = false */)
{
if (atlas == _fontAtlas)
{
FontAtlasCache::releaseFontAtlas(atlas);
return;
}
if (_fontAtlas)
{
_batchNodes.clear(); //这里已经重置
FontAtlasCache::releaseFontAtlas(_fontAtlas);
_fontAtlas = nullptr;
}
_fontAtlas = atlas;
//.....
}
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |