关于 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,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, origin.width,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, origin.width,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的更多相关文章

  1. Centos 6.8 安装 Protocol Buffers , v3.2.0有 BUG ,安装 3.1.0

    Centos 6.8 安装 Protocol Buffers   , v3.2.0有 BUG ,安装 3.1.0 切换到用户目录 cd ~ 安装 python2.7,须加入zlib wget http ...

  2. Cocos2d-JS V3.10 一个小bug提示

    感谢读者古事东流反馈,新版V3.10的音乐播放接口存在一个bug. 重复播放一个音乐,会出现音乐停止的状况. debug了一下,发现src的对比有点问题.传入的url是相对路径,但背景bgMusic. ...

  3. 最新版jQuery v3.3.1的BUG以及解决办法(什么问题不重要,怎么解决问题才重要)

    发现问题 最新版的 FineUIPro v5.2.0 中,我们将内置的 jQuery v1.12.4 升级到 jQuery v3.3.1 ,可以看升级记录: +升级到jQuery v3.3.1.    ...

  4. 高性能 TCP & UDP 通信框架 HP-Socket v3.5.3

    HP-Socket 是一套通用的高性能 TCP/UDP 通信框架,包含服务端组件.客户端组件和 Agent 组件,广泛适用于各种不同应用场景的 TCP/UDP 通信系统,提供 C/C++.C#.Del ...

  5. sass --watch 失败bug

    NameError: uninitialized constant Sass::Plugin::Compiler::SassListen 网上说法是sass v3.2.10有bug 但是我版本3.5. ...

  6. StackExchange.Redis通用封装类分享(转)

    阅读目录 ConnectionMultiplexer 封装 RedisHelper 通用操作类封 String类型的封装 List类型的封装 Hash类型的封装 SortedSet 类型的封装 key ...

  7. StackExchange.Redis通用封装类分享

    前两天朋友问我,有没有使用过StackExchange.Redis,问我要个封装类,由于之前都是使用ServiceStack.Redis,由于ServiceStack.Redis v4版本后是收费版的 ...

  8. Cocos Studio和Cocos2d-x版本对应关系

    链接地址:http://www.cocoachina.com/bbs/read.php?tid=182077 可以在cocos2d.cpp中查看2d-x的版本信息.   版本对应列表: Studio2 ...

  9. 开源敏捷测试管理& 开源BUG跟踪管理软件itest(爱测试) V3.3.0隆重发布

    v3.3.0 下载地址 :itest下载 码云源码地址 https://gitee.com/itestwork/itest 开源中国  itest项目地址   https://www.oschina. ...

随机推荐

  1. Jquery添加移除样式

    获取与设置样式 获取class和设置class都可以使用attr()方法来完成.例如使用attr()方法来获取p元素的class,JQuery代码如下: var p_class = $("p ...

  2. 2013 ACM/ICPC南京邀请赛B题(求割点扩展)

    题目链接:http://icpc.njust.edu.cn/Contest/194/Problem/B B - TWO NODES 时间限制: 10000 MS 内存限制: 65535 KB 问题描述 ...

  3. printf函数重定向

    printf函数底层会调用fputc函数 /*重定向c库函数printf到USART1*/ int fputc(int ch, FILE *f) { /*发送一个字节数据USART1 */ USART ...

  4. HDU 5438 Ponds (DFS,并查集)

    题意:给定一个图,然后让你把边数为1的结点删除,然后求连通块结点数为奇的权值和. 析:这个题要注意,如果删除一些结点后,又形成了新的边数为1的结点,也应该要删除,这是坑,其他的,先用并查集判一下环,然 ...

  5. 分享吉林大学机械科学与工程学院,zhao jun 博士的Halcon学习过程及知识分享

    分享吉林大学机械科学与工程学院,zhao jun 博士的Halcon学习过程及知识分享 全文转载zhao jun 博士的新浪博客,版权为zhaojun博士所有 原文地址:http://blog.sin ...

  6. Spring REST实践之客户端和测试

    RestTemplate 可参考spring实战来写这部分. RestTemplate免于编写乏味的样板代码,RestTemplate定义了33个与REST资源交互的方法,涵盖了HTTP动作的各种形式 ...

  7. CSS(04) 定位

    布局常用的三种:标准流.定位.浮动: 1.文档流-标准流 窗体自上而下分成一行行(元素在 (X)HTML 中的位置),并在一行行中从左到右排放元素: 2.CSS 定位 Position 属性(绝对定位 ...

  8. ActionBarCompat

    布局文件中添加menu menu_main.xml <?xml version="1.0" encoding="utf-8"?> <menu ...

  9. C++ Primer 学习笔记_67_面向对象编程 --转换与继承、复制控制与继承

    面向对象编程 --转换与继承.复制控制与继承 I.转换与继承 引言: 由于每一个派生类对象都包括一个基类部分,因此能够像使用基类对象一样在派生类对象上执行操作. 对于指针/引用,能够将派生类对象的指针 ...

  10. 【转】浅析linux内存模型

    转自:http://pengpeng.iteye.com/blog/875521 0. 内存基本知识 我们通常称 linux的内存子系统为:虚拟内存子系统(virtual memory system) ...