关于 2dx v3.7 UIScale9Sprite的bug

关于 2dx v3.7 UIScale9Sprite的bug,第1张

概述关于 2dx v3.7 UIScale9Sprite的bug 刚把引擎从js binding v3.0升级到v3.7,发现了一些bug,这里先说说关于scale9sprite的 1. 关于capInsets https://github.com/cocos2d/cocos2d-x/issues/13560 问题描述:使用cocosbuilder创建的九宫格图片,如果capInserts没有设置(即 关于 2dx v3.7 UIScale9Sprite的BUG

刚把引擎从Js binding v3.0升级到v3.7,发现了一些BUG,这里先说说关于scale9sprite的

1. 关于cAPInsets

https://github.com/cocos2d/cocos2d-x/issues/13560
问题描述:使用cocosbuilder创建的九宫格图片,如果cAPInserts没有设置(即ZERO),那么九宫格使用的应该是默认缩放,但是结果却是没有缩放。
builder中:

运行结果(上图使用builder默认inserts产生的错误九宫格,下图正常九宫格缩放):

解决方案:
bool Scale9Sprite::updateWithSprite(Sprite* sprite,const Rect& textureRect,bool rotated,const Vec2 &offset,const Size &originalSize,const Rect& cAPInsets){    //...    // Set the given rect's size as original size     _spriteRect = rect;     _offset = offset;     _spriteFrameRotated = rotated;      _originalSize = size;     _preferredSize = size;     // if(!cAPInsets.equals(Rect::ZERO)) //此处的if判断应该去掉,直接赋值给_cAPInsetsInternal      {          _cAPInsetsInternal = cAPInsets;      }      if (_scale9Enabled)      {          this->createSlicedSprites();      }    //...}
原因:
setSpriteFrame时,默认传入的cAPInsets是zero,注意_insetRight,_insetBottom 的值
voID Scale9Sprite::setSpriteFrame(SpriteFrame * spriteFrame,const Rect& cAPInsets)    {        Sprite * sprite = Sprite::createWithTexture(spriteFrame->getTexture());        this->updateWithSprite(sprite,spriteFrame->getRect(),spriteFrame->isRotated(),spriteFrame->getoffset(),spriteFrame->getoriginalSize(),cAPInsets);        // reset insets        this->_insetleft = cAPInsets.origin.x; // == 0        this->_insettop = cAPInsets.origin.y;// == 0        this->_insetRight = _originalSize.wIDth - _insetleft - cAPInsets.size.wIDth; //== wIDth        this->_insetBottom = _originalSize.height - _insettop - cAPInsets.size.height;// ==height    }

然后cocosbuilder加载scale9sprite时,顺序调用setInsetleft(0),setInsettop(0),setInsetRight(0),setInsetBottom(0)
解析ccb的代码如下:

voID Scale9SpriteLoader::onHandlePropTypefloat(Node * pNode,Node * pParent,const char * pPropertyname,float pfloat,CCBReader * ccbReader) {    if(strcmp(pPropertyname,PROPERTY_INSETleft) == 0) {        ((cocos2d::ui::Scale9Sprite *)pNode)->setInsetleft(pfloat);    } else if(strcmp(pPropertyname,PROPERTY_INSETtop) == 0) {        ((cocos2d::ui::Scale9Sprite *)pNode)->setInsettop(pfloat);    } else if(strcmp(pPropertyname,PROPERTY_INSETRIGHT) == 0) {        ((cocos2d::ui::Scale9Sprite *)pNode)->setInsetRight(pfloat);    } else if(strcmp(pPropertyname,PROPERTY_INSETBottOM) == 0) {        ((cocos2d::ui::Scale9Sprite *)pNode)->setInsetBottom(pfloat);    } else {        NodeLoader::onHandlePropTypefloat(pNode,pParent,pPropertyname,pfloat,ccbReader);    }}

4个函数都会调用updateCAPInset,并在其中调用setCAPInsets,在setCAPInsets中调用updateWithSprite和重新计算_insetRight,_insetBottom的值,
那么问题来了,执行到setInsetRight(0)时:

voID Scale9Sprite::setCAPInsets(const Rect& cAPInsets)    {        Size contentSize = this->_contentSize;        this->updateWithSprite(this->_scale9Image,_spriteRect,_spriteFrameRotated,_offset,_originalSize,cAPInsets); // 这里传入的cAPInsets = (0,origin.wIDth,0),此值不等于zero,在updateWithSprite中会赋值给_cAPInsetsInternal        this->_insetleft = cAPInsets.origin.x;        this->_insettop = cAPInsets.origin.y;        this->_insetRight = _originalSize.wIDth - _insetleft - cAPInsets.size.wIDth;        this->_insetBottom = _originalSize.height - _insettop - cAPInsets.size.height;        this->setContentSize(contentSize);    }

然后再在最后一次调用 setInsetBottom(0)时,cAPInsets==zero,因为有if(!cAPInsets.equals(Rect::ZERO))判断,不会覆盖_cAPInsetsInternal,那么_cAPInsetsInternal就成了一个错误的临时值(0,0),其实我们要的应该是最后一次调用后的值zero,即使用默认的九宫格缩放

// If there is no specifIEd center region    if ( _cAPInsetsInternal.equals(Rect::ZERO) )    {        // log("... cap insets not specifIEd : using default cap insets ...");        _cAPInsetsInternal = Rect(wIDth /3,height /3,wIDth /3,height /3);    }

当_cAPInsetsInternal == (0,0)时,默认值也不会被使用,那么九宫格缩放当然是错误的啦。
所以在updateWithSprite中,// if(!cAPInsets.equals(Rect::ZERO)) //此处的if判断应该去掉,直接赋值给_cAPInsetsInternal ,避免多次setCAPInset时使用中间的临时值。

=======================华丽的分割线=======================

2. 创建的九宫格图片偏移了几个像素

https://github.com/cocos2d/cocos2d-x/issues/13564
如图(右为普通sprite,左为scale9sprite):

createSlicedSprites接口中计算offsetposition时:

voID Scale9Sprite::createSlicedSprites()    {        float wIDth = _originalSize.wIDth;        float height = _originalSize.height;    Vec2 offsetposition(ceil(_offset.x + (_originalSize.wIDth - _spriteRect.size.wIDth) / 2),ceil(_offset.y + (_originalSize.height - _spriteRect.size.height) / 2));    //...   }

此处计算偏移时为什么要向上取整,总之我不是很明白,希望有人能解释一下,谢谢。
- 导致的问题:
生成的九宫格图片偏移了几个像素,这个问题一般情况下不明显,我是在使用pList拼图时发现, 九宫格图片下方出现了其他图片的条纹,自己图片的上方少了几排像素。
然后找到上面的代码,去掉ceil后,发现恢复了一些,如图(左图还是能看到上方的角少了点):

把ceil换成floor后,发现正常了,如图(texturepacker打开shape outlines):

那么问题来了:
按我的理解此处不应该使用ceil,也不应该使用floor,但为什么使用floor后才是正常的。有空的朋友可以使用texturepacker打个纹理图集测试一下,把shape outlines勾选上就能看到图片的矩形区域,看看你们创建出来的scale9sprite矩形区域是否发生了偏移。

=======================华丽的分割线=======================

总结

以上是内存溢出为你收集整理的关于 2dx v3.7 UIScale9Sprite的bug全部内容,希望文章能够帮你解决关于 2dx v3.7 UIScale9Sprite的bug所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/web/1069689.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-05-26
下一篇2022-05-26

发表评论

登录后才能评论

评论列表(0条)

    保存