mirror of https://github.com/axmolengine/axmol.git
add UIScale9Sprite implementation
This commit is contained in:
parent
32ed796657
commit
717f20571b
|
@ -4202,6 +4202,8 @@
|
||||||
29CB8F511929D64500C841D6 /* base */ = {
|
29CB8F511929D64500C841D6 /* base */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
2958244919873D8E00F9746D /* UIScale9Sprite.cpp */,
|
||||||
|
2958244A19873D8E00F9746D /* UIScale9Sprite.h */,
|
||||||
29080DEB191B82CE0066F8DF /* UIDeprecated.h */,
|
29080DEB191B82CE0066F8DF /* UIDeprecated.h */,
|
||||||
29BDBA52195D597A003225C9 /* UIDeprecated.cpp */,
|
29BDBA52195D597A003225C9 /* UIDeprecated.cpp */,
|
||||||
2905FA1318CF08D100240AA3 /* UIWidget.cpp */,
|
2905FA1318CF08D100240AA3 /* UIWidget.cpp */,
|
||||||
|
@ -4253,8 +4255,6 @@
|
||||||
2905F9F318CF08D000240AA3 /* UICheckBox.h */,
|
2905F9F318CF08D000240AA3 /* UICheckBox.h */,
|
||||||
2905F9F618CF08D000240AA3 /* UIImageView.cpp */,
|
2905F9F618CF08D000240AA3 /* UIImageView.cpp */,
|
||||||
2905F9F718CF08D000240AA3 /* UIImageView.h */,
|
2905F9F718CF08D000240AA3 /* UIImageView.h */,
|
||||||
2958244919873D8E00F9746D /* UIScale9Sprite.cpp */,
|
|
||||||
2958244A19873D8E00F9746D /* UIScale9Sprite.h */,
|
|
||||||
);
|
);
|
||||||
name = widgets;
|
name = widgets;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
|
|
@ -23,3 +23,921 @@
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#include "UIScale9Sprite.h"
|
#include "UIScale9Sprite.h"
|
||||||
|
#include "2d/CCSprite.h"
|
||||||
|
#include "2d/CCSpriteFrameCache.h"
|
||||||
|
#include "base/CCVector.h"
|
||||||
|
#include "base/CCDirector.h"
|
||||||
|
|
||||||
|
NS_CC_BEGIN
|
||||||
|
namespace ui {
|
||||||
|
|
||||||
|
Scale9Sprite::Scale9Sprite()
|
||||||
|
: _spritesGenerated(false)
|
||||||
|
, _spriteFrameRotated(false)
|
||||||
|
, _positionsAreDirty(false)
|
||||||
|
, _scale9Image(nullptr)
|
||||||
|
, _topLeft(nullptr)
|
||||||
|
, _top(nullptr)
|
||||||
|
, _topRight(nullptr)
|
||||||
|
, _left(nullptr)
|
||||||
|
, _centre(nullptr)
|
||||||
|
, _right(nullptr)
|
||||||
|
, _bottomLeft(nullptr)
|
||||||
|
, _bottom(nullptr)
|
||||||
|
, _bottomRight(nullptr)
|
||||||
|
, _insetLeft(0)
|
||||||
|
, _insetTop(0)
|
||||||
|
, _insetRight(0)
|
||||||
|
, _insetBottom(0),
|
||||||
|
_scale9Enabled(true)
|
||||||
|
{
|
||||||
|
this->setAnchorPoint(Vec2(0.5,0.5));
|
||||||
|
}
|
||||||
|
|
||||||
|
Scale9Sprite::~Scale9Sprite()
|
||||||
|
{
|
||||||
|
this->cleanupSlicedSprites();
|
||||||
|
CC_SAFE_RELEASE(_scale9Image);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scale9Sprite::cleanupSlicedSprites()
|
||||||
|
{
|
||||||
|
CC_SAFE_RELEASE(_topLeft);
|
||||||
|
CC_SAFE_RELEASE(_top);
|
||||||
|
CC_SAFE_RELEASE(_topRight);
|
||||||
|
CC_SAFE_RELEASE(_left);
|
||||||
|
CC_SAFE_RELEASE(_centre);
|
||||||
|
CC_SAFE_RELEASE(_right);
|
||||||
|
CC_SAFE_RELEASE(_bottomLeft);
|
||||||
|
CC_SAFE_RELEASE(_bottom);
|
||||||
|
CC_SAFE_RELEASE(_bottomRight);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Scale9Sprite::init()
|
||||||
|
{
|
||||||
|
return this->init(NULL, Rect::ZERO, Rect::ZERO);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Scale9Sprite::init(Sprite* sprite, const Rect& rect, const Rect& capInsets)
|
||||||
|
{
|
||||||
|
return this->init(sprite, rect, false, capInsets);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Scale9Sprite::init(Sprite* sprite, const Rect& rect, bool rotated, const Rect& capInsets)
|
||||||
|
{
|
||||||
|
if(sprite)
|
||||||
|
{
|
||||||
|
this->updateWithSprite(sprite, rect, rotated, capInsets);
|
||||||
|
}
|
||||||
|
this->setCascadeColorEnabled(true);
|
||||||
|
this->setCascadeOpacityEnabled(true);
|
||||||
|
this->setAnchorPoint(Vec2(0.5f, 0.5f));
|
||||||
|
this->_positionsAreDirty = true;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define TRANSLATE_X(x, y, xtranslate) \
|
||||||
|
x+=xtranslate; \
|
||||||
|
|
||||||
|
#define TRANSLATE_Y(x, y, ytranslate) \
|
||||||
|
y+=ytranslate; \
|
||||||
|
|
||||||
|
bool Scale9Sprite::updateWithSprite(Sprite* sprite, const Rect& originalRect, bool rotated, const Rect& capInsets)
|
||||||
|
{
|
||||||
|
GLubyte opacity = getOpacity();
|
||||||
|
Color3B color = getColor();
|
||||||
|
Rect rect(originalRect);
|
||||||
|
|
||||||
|
// Release old sprites
|
||||||
|
_protectedChildren.clear();
|
||||||
|
|
||||||
|
this->cleanupSlicedSprites();
|
||||||
|
|
||||||
|
|
||||||
|
if(this->_scale9Image != sprite)
|
||||||
|
{
|
||||||
|
CC_SAFE_RELEASE(this->_scale9Image);
|
||||||
|
_scale9Image = sprite;
|
||||||
|
CC_SAFE_RETAIN(_scale9Image);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_scale9Image)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
_capInsets = capInsets;
|
||||||
|
_spriteFrameRotated = rotated;
|
||||||
|
|
||||||
|
// If there is no given rect
|
||||||
|
if ( rect.equals(Rect::ZERO) )
|
||||||
|
{
|
||||||
|
// Get the texture size as original
|
||||||
|
Size textureSize = _scale9Image->getTexture()->getContentSize();
|
||||||
|
|
||||||
|
rect = Rect(0, 0, textureSize.width, textureSize.height);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the given rect's size as original size
|
||||||
|
_spriteRect = rect;
|
||||||
|
_originalSize = rect.size;
|
||||||
|
_preferredSize = _originalSize;
|
||||||
|
_capInsetsInternal = capInsets;
|
||||||
|
|
||||||
|
|
||||||
|
this->createSlicedSprites(rect, rotated);
|
||||||
|
|
||||||
|
this->setContentSize(rect.size);
|
||||||
|
|
||||||
|
if (_spritesGenerated)
|
||||||
|
{
|
||||||
|
// Restore color and opacity
|
||||||
|
this->setOpacity(opacity);
|
||||||
|
this->setColor(color);
|
||||||
|
}
|
||||||
|
_spritesGenerated = true;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scale9Sprite::createSlicedSprites(const Rect& rect, bool rotated)
|
||||||
|
{
|
||||||
|
float w = rect.size.width;
|
||||||
|
float h = rect.size.height;
|
||||||
|
|
||||||
|
// If there is no specified center region
|
||||||
|
if ( _capInsetsInternal.equals(Rect::ZERO) )
|
||||||
|
{
|
||||||
|
// log("... cap insets not specified : using default cap insets ...");
|
||||||
|
_capInsetsInternal = Rect(w/3, h/3, w/3, h/3);
|
||||||
|
}
|
||||||
|
|
||||||
|
float left_w = _capInsetsInternal.origin.x;
|
||||||
|
float center_w = _capInsetsInternal.size.width;
|
||||||
|
float right_w = rect.size.width - (left_w + center_w);
|
||||||
|
|
||||||
|
float top_h = _capInsetsInternal.origin.y;
|
||||||
|
float center_h = _capInsetsInternal.size.height;
|
||||||
|
float bottom_h = rect.size.height - (top_h + center_h);
|
||||||
|
|
||||||
|
// calculate rects
|
||||||
|
|
||||||
|
// ... top row
|
||||||
|
float x = 0.0;
|
||||||
|
float y = 0.0;
|
||||||
|
|
||||||
|
// top left
|
||||||
|
Rect lefttopbounds = Rect(x, y, left_w, top_h);
|
||||||
|
|
||||||
|
// top center
|
||||||
|
TRANSLATE_X(x, y, left_w);
|
||||||
|
Rect centertopbounds = Rect(x, y, center_w, top_h);
|
||||||
|
|
||||||
|
// top right
|
||||||
|
TRANSLATE_X(x, y, center_w);
|
||||||
|
Rect righttopbounds = Rect(x, y, right_w, top_h);
|
||||||
|
|
||||||
|
// ... center row
|
||||||
|
x = 0.0;
|
||||||
|
y = 0.0;
|
||||||
|
TRANSLATE_Y(x, y, top_h);
|
||||||
|
|
||||||
|
// center left
|
||||||
|
Rect leftcenterbounds = Rect(x, y, left_w, center_h);
|
||||||
|
|
||||||
|
// center center
|
||||||
|
TRANSLATE_X(x, y, left_w);
|
||||||
|
Rect centerbounds = Rect(x, y, center_w, center_h);
|
||||||
|
|
||||||
|
// center right
|
||||||
|
TRANSLATE_X(x, y, center_w);
|
||||||
|
Rect rightcenterbounds = Rect(x, y, right_w, center_h);
|
||||||
|
|
||||||
|
// ... bottom row
|
||||||
|
x = 0.0;
|
||||||
|
y = 0.0;
|
||||||
|
TRANSLATE_Y(x, y, top_h);
|
||||||
|
TRANSLATE_Y(x, y, center_h);
|
||||||
|
|
||||||
|
// bottom left
|
||||||
|
Rect leftbottombounds = Rect(x, y, left_w, bottom_h);
|
||||||
|
|
||||||
|
// bottom center
|
||||||
|
TRANSLATE_X(x, y, left_w);
|
||||||
|
Rect centerbottombounds = Rect(x, y, center_w, bottom_h);
|
||||||
|
|
||||||
|
// bottom right
|
||||||
|
TRANSLATE_X(x, y, center_w);
|
||||||
|
Rect rightbottombounds = Rect(x, y, right_w, bottom_h);
|
||||||
|
|
||||||
|
|
||||||
|
Rect rotatedcenterbounds = centerbounds;
|
||||||
|
Rect rotatedrightbottombounds = rightbottombounds;
|
||||||
|
Rect rotatedleftbottombounds = leftbottombounds;
|
||||||
|
Rect rotatedrighttopbounds = righttopbounds;
|
||||||
|
Rect rotatedlefttopbounds = lefttopbounds;
|
||||||
|
Rect rotatedrightcenterbounds = rightcenterbounds;
|
||||||
|
Rect rotatedleftcenterbounds = leftcenterbounds;
|
||||||
|
Rect rotatedcenterbottombounds = centerbottombounds;
|
||||||
|
Rect rotatedcentertopbounds = centertopbounds;
|
||||||
|
|
||||||
|
if (!rotated) {
|
||||||
|
// log("!rotated");
|
||||||
|
|
||||||
|
AffineTransform t = AffineTransform::IDENTITY;
|
||||||
|
t = AffineTransformTranslate(t, rect.origin.x, rect.origin.y);
|
||||||
|
|
||||||
|
rotatedcenterbounds = RectApplyAffineTransform(rotatedcenterbounds, t);
|
||||||
|
rotatedrightbottombounds = RectApplyAffineTransform(rotatedrightbottombounds, t);
|
||||||
|
rotatedleftbottombounds = RectApplyAffineTransform(rotatedleftbottombounds, t);
|
||||||
|
rotatedrighttopbounds = RectApplyAffineTransform(rotatedrighttopbounds, t);
|
||||||
|
rotatedlefttopbounds = RectApplyAffineTransform(rotatedlefttopbounds, t);
|
||||||
|
rotatedrightcenterbounds = RectApplyAffineTransform(rotatedrightcenterbounds, t);
|
||||||
|
rotatedleftcenterbounds = RectApplyAffineTransform(rotatedleftcenterbounds, t);
|
||||||
|
rotatedcenterbottombounds = RectApplyAffineTransform(rotatedcenterbottombounds, t);
|
||||||
|
rotatedcentertopbounds = RectApplyAffineTransform(rotatedcentertopbounds, t);
|
||||||
|
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// set up transformation of coordinates
|
||||||
|
// to handle the case where the sprite is stored rotated
|
||||||
|
// in the spritesheet
|
||||||
|
// log("rotated");
|
||||||
|
|
||||||
|
AffineTransform t = AffineTransform::IDENTITY;
|
||||||
|
|
||||||
|
t = AffineTransformTranslate(t, rect.size.height+rect.origin.x, rect.origin.y);
|
||||||
|
t = AffineTransformRotate(t, 1.57079633f);
|
||||||
|
|
||||||
|
centerbounds = RectApplyAffineTransform(centerbounds, t);
|
||||||
|
rightbottombounds = RectApplyAffineTransform(rightbottombounds, t);
|
||||||
|
leftbottombounds = RectApplyAffineTransform(leftbottombounds, t);
|
||||||
|
righttopbounds = RectApplyAffineTransform(righttopbounds, t);
|
||||||
|
lefttopbounds = RectApplyAffineTransform(lefttopbounds, t);
|
||||||
|
rightcenterbounds = RectApplyAffineTransform(rightcenterbounds, t);
|
||||||
|
leftcenterbounds = RectApplyAffineTransform(leftcenterbounds, t);
|
||||||
|
centerbottombounds = RectApplyAffineTransform(centerbottombounds, t);
|
||||||
|
centertopbounds = RectApplyAffineTransform(centertopbounds, t);
|
||||||
|
|
||||||
|
rotatedcenterbounds.origin = centerbounds.origin;
|
||||||
|
rotatedrightbottombounds.origin = rightbottombounds.origin;
|
||||||
|
rotatedleftbottombounds.origin = leftbottombounds.origin;
|
||||||
|
rotatedrighttopbounds.origin = righttopbounds.origin;
|
||||||
|
rotatedlefttopbounds.origin = lefttopbounds.origin;
|
||||||
|
rotatedrightcenterbounds.origin = rightcenterbounds.origin;
|
||||||
|
rotatedleftcenterbounds.origin = leftcenterbounds.origin;
|
||||||
|
rotatedcenterbottombounds.origin = centerbottombounds.origin;
|
||||||
|
rotatedcentertopbounds.origin = centertopbounds.origin;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Centre
|
||||||
|
_centre = Sprite::createWithTexture(_scale9Image->getTexture(), rotatedcenterbounds, rotated);
|
||||||
|
_centre->retain();
|
||||||
|
this->addProtectedChild(_centre);
|
||||||
|
|
||||||
|
|
||||||
|
// Top
|
||||||
|
_top = Sprite::createWithTexture(_scale9Image->getTexture(), rotatedcentertopbounds, rotated);
|
||||||
|
_top->retain();
|
||||||
|
this->addProtectedChild(_top);
|
||||||
|
|
||||||
|
// Bottom
|
||||||
|
_bottom = Sprite::createWithTexture(_scale9Image->getTexture(), rotatedcenterbottombounds, rotated);
|
||||||
|
_bottom->retain();
|
||||||
|
this->addProtectedChild(_bottom);
|
||||||
|
|
||||||
|
// Left
|
||||||
|
_left = Sprite::createWithTexture(_scale9Image->getTexture(), rotatedleftcenterbounds, rotated);
|
||||||
|
_left->retain();
|
||||||
|
this->addProtectedChild(_left);
|
||||||
|
|
||||||
|
// Right
|
||||||
|
_right = Sprite::createWithTexture(_scale9Image->getTexture(), rotatedrightcenterbounds, rotated);
|
||||||
|
_right->retain();
|
||||||
|
this->addProtectedChild(_right);
|
||||||
|
|
||||||
|
// Top left
|
||||||
|
_topLeft = Sprite::createWithTexture(_scale9Image->getTexture(), rotatedlefttopbounds, rotated);
|
||||||
|
_topLeft->retain();
|
||||||
|
this->addProtectedChild(_topLeft);
|
||||||
|
|
||||||
|
// Top right
|
||||||
|
_topRight = Sprite::createWithTexture(_scale9Image->getTexture(), rotatedrighttopbounds, rotated);
|
||||||
|
_topRight->retain();
|
||||||
|
this->addProtectedChild(_topRight);
|
||||||
|
|
||||||
|
// Bottom left
|
||||||
|
_bottomLeft = Sprite::createWithTexture(_scale9Image->getTexture(), rotatedleftbottombounds, rotated);
|
||||||
|
_bottomLeft->retain();
|
||||||
|
this->addProtectedChild(_bottomLeft);
|
||||||
|
|
||||||
|
// Bottom right
|
||||||
|
_bottomRight = Sprite::createWithTexture(_scale9Image->getTexture(), rotatedrightbottombounds, rotated);
|
||||||
|
_bottomRight->retain();
|
||||||
|
this->addProtectedChild(_bottomRight);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scale9Sprite::setContentSize(const Size &size)
|
||||||
|
{
|
||||||
|
Node::setContentSize(size);
|
||||||
|
this->_positionsAreDirty = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scale9Sprite::updatePositions()
|
||||||
|
{
|
||||||
|
// Check that instances are non-NULL
|
||||||
|
if(!((_topLeft) &&
|
||||||
|
(_topRight) &&
|
||||||
|
(_bottomRight) &&
|
||||||
|
(_bottomLeft) &&
|
||||||
|
(_centre))) {
|
||||||
|
// if any of the above sprites are NULL, return
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Size size = this->_contentSize;
|
||||||
|
|
||||||
|
float sizableWidth = size.width - _topLeft->getContentSize().width - _topRight->getContentSize().width;
|
||||||
|
float sizableHeight = size.height - _topLeft->getContentSize().height - _bottomRight->getContentSize().height;
|
||||||
|
|
||||||
|
float horizontalScale = sizableWidth/_centre->getContentSize().width;
|
||||||
|
float verticalScale = sizableHeight/_centre->getContentSize().height;
|
||||||
|
|
||||||
|
_centre->setScaleX(horizontalScale);
|
||||||
|
_centre->setScaleY(verticalScale);
|
||||||
|
|
||||||
|
float rescaledWidth = _centre->getContentSize().width * horizontalScale;
|
||||||
|
float rescaledHeight = _centre->getContentSize().height * verticalScale;
|
||||||
|
|
||||||
|
float leftWidth = _bottomLeft->getContentSize().width;
|
||||||
|
float bottomHeight = _bottomLeft->getContentSize().height;
|
||||||
|
|
||||||
|
_bottomLeft->setAnchorPoint(Vec2(0,0));
|
||||||
|
_bottomRight->setAnchorPoint(Vec2(0,0));
|
||||||
|
_topLeft->setAnchorPoint(Vec2(0,0));
|
||||||
|
_topRight->setAnchorPoint(Vec2(0,0));
|
||||||
|
_left->setAnchorPoint(Vec2(0,0));
|
||||||
|
_right->setAnchorPoint(Vec2(0,0));
|
||||||
|
_top->setAnchorPoint(Vec2(0,0));
|
||||||
|
_bottom->setAnchorPoint(Vec2(0,0));
|
||||||
|
_centre->setAnchorPoint(Vec2(0,0));
|
||||||
|
|
||||||
|
// Position corners
|
||||||
|
_bottomLeft->setPosition(Vec2(0,0));
|
||||||
|
_bottomRight->setPosition(Vec2(leftWidth+rescaledWidth,0));
|
||||||
|
_topLeft->setPosition(Vec2(0, bottomHeight+rescaledHeight));
|
||||||
|
_topRight->setPosition(Vec2(leftWidth+rescaledWidth, bottomHeight+rescaledHeight));
|
||||||
|
|
||||||
|
// Scale and position borders
|
||||||
|
_left->setPosition(Vec2(0, bottomHeight));
|
||||||
|
_left->setScaleY(verticalScale);
|
||||||
|
_right->setPosition(Vec2(leftWidth+rescaledWidth,bottomHeight));
|
||||||
|
_right->setScaleY(verticalScale);
|
||||||
|
_bottom->setPosition(Vec2(leftWidth,0));
|
||||||
|
_bottom->setScaleX(horizontalScale);
|
||||||
|
_top->setPosition(Vec2(leftWidth,bottomHeight+rescaledHeight));
|
||||||
|
_top->setScaleX(horizontalScale);
|
||||||
|
|
||||||
|
// Position centre
|
||||||
|
_centre->setPosition(Vec2(leftWidth, bottomHeight));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Scale9Sprite::initWithFile(const std::string& file, const Rect& rect, const Rect& capInsets)
|
||||||
|
{
|
||||||
|
Sprite *sprite = Sprite::create(file);
|
||||||
|
bool pReturn = this->init(sprite, rect, capInsets);
|
||||||
|
return pReturn;
|
||||||
|
}
|
||||||
|
|
||||||
|
Scale9Sprite* Scale9Sprite::create(const std::string& file, const Rect& rect, const Rect& capInsets)
|
||||||
|
{
|
||||||
|
Scale9Sprite* pReturn = new Scale9Sprite();
|
||||||
|
if ( pReturn && pReturn->initWithFile(file, rect, capInsets) )
|
||||||
|
{
|
||||||
|
pReturn->autorelease();
|
||||||
|
return pReturn;
|
||||||
|
}
|
||||||
|
CC_SAFE_DELETE(pReturn);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Scale9Sprite::initWithFile(const std::string& file, const Rect& rect)
|
||||||
|
{
|
||||||
|
bool pReturn = this->initWithFile(file, rect, Rect::ZERO);
|
||||||
|
return pReturn;
|
||||||
|
}
|
||||||
|
|
||||||
|
Scale9Sprite* Scale9Sprite::create(const std::string& file, const Rect& rect)
|
||||||
|
{
|
||||||
|
Scale9Sprite* pReturn = new Scale9Sprite();
|
||||||
|
if ( pReturn && pReturn->initWithFile(file, rect) )
|
||||||
|
{
|
||||||
|
pReturn->autorelease();
|
||||||
|
return pReturn;
|
||||||
|
}
|
||||||
|
CC_SAFE_DELETE(pReturn);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Scale9Sprite::initWithFile(const Rect& capInsets, const std::string& file)
|
||||||
|
{
|
||||||
|
bool pReturn = this->initWithFile(file, Rect::ZERO, capInsets);
|
||||||
|
return pReturn;
|
||||||
|
}
|
||||||
|
|
||||||
|
Scale9Sprite* Scale9Sprite::create(const Rect& capInsets, const std::string& file)
|
||||||
|
{
|
||||||
|
Scale9Sprite* pReturn = new Scale9Sprite();
|
||||||
|
if ( pReturn && pReturn->initWithFile(capInsets, file) )
|
||||||
|
{
|
||||||
|
pReturn->autorelease();
|
||||||
|
return pReturn;
|
||||||
|
}
|
||||||
|
CC_SAFE_DELETE(pReturn);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Scale9Sprite::initWithFile(const std::string& file)
|
||||||
|
{
|
||||||
|
bool pReturn = this->initWithFile(file, Rect::ZERO);
|
||||||
|
return pReturn;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Scale9Sprite* Scale9Sprite::create(const std::string& file)
|
||||||
|
{
|
||||||
|
Scale9Sprite* pReturn = new Scale9Sprite();
|
||||||
|
if ( pReturn && pReturn->initWithFile(file) )
|
||||||
|
{
|
||||||
|
pReturn->autorelease();
|
||||||
|
return pReturn;
|
||||||
|
}
|
||||||
|
CC_SAFE_DELETE(pReturn);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Scale9Sprite::initWithSpriteFrame(SpriteFrame* spriteFrame, const Rect& capInsets)
|
||||||
|
{
|
||||||
|
Texture2D* texture = spriteFrame->getTexture();
|
||||||
|
CCASSERT(texture != NULL, "CCTexture must be not nil");
|
||||||
|
|
||||||
|
Sprite *sprite = Sprite::createWithSpriteFrame(spriteFrame);
|
||||||
|
CCASSERT(sprite != NULL, "sprite must be not nil");
|
||||||
|
|
||||||
|
bool pReturn = this->init(sprite, spriteFrame->getRect(), spriteFrame->isRotated(), capInsets);
|
||||||
|
return pReturn;
|
||||||
|
}
|
||||||
|
|
||||||
|
Scale9Sprite* Scale9Sprite::createWithSpriteFrame(SpriteFrame* spriteFrame, const Rect& capInsets)
|
||||||
|
{
|
||||||
|
Scale9Sprite* pReturn = new Scale9Sprite();
|
||||||
|
if ( pReturn && pReturn->initWithSpriteFrame(spriteFrame, capInsets) )
|
||||||
|
{
|
||||||
|
pReturn->autorelease();
|
||||||
|
return pReturn;
|
||||||
|
}
|
||||||
|
CC_SAFE_DELETE(pReturn);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
bool Scale9Sprite::initWithSpriteFrame(SpriteFrame* spriteFrame)
|
||||||
|
{
|
||||||
|
CCASSERT(spriteFrame != NULL, "Invalid spriteFrame for sprite");
|
||||||
|
bool pReturn = this->initWithSpriteFrame(spriteFrame, Rect::ZERO);
|
||||||
|
return pReturn;
|
||||||
|
}
|
||||||
|
|
||||||
|
Scale9Sprite* Scale9Sprite::createWithSpriteFrame(SpriteFrame* spriteFrame)
|
||||||
|
{
|
||||||
|
Scale9Sprite* pReturn = new Scale9Sprite();
|
||||||
|
if ( pReturn && pReturn->initWithSpriteFrame(spriteFrame) )
|
||||||
|
{
|
||||||
|
pReturn->autorelease();
|
||||||
|
return pReturn;
|
||||||
|
}
|
||||||
|
CC_SAFE_DELETE(pReturn);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Scale9Sprite::initWithSpriteFrameName(const std::string& spriteFrameName, const Rect& capInsets)
|
||||||
|
{
|
||||||
|
CCASSERT((SpriteFrameCache::getInstance()) != NULL, "SpriteFrameCache::getInstance() must be non-NULL");
|
||||||
|
|
||||||
|
SpriteFrame *frame = SpriteFrameCache::getInstance()->getSpriteFrameByName(spriteFrameName);
|
||||||
|
CCASSERT(frame != NULL, "CCSpriteFrame must be non-NULL");
|
||||||
|
|
||||||
|
if (NULL == frame) return false;
|
||||||
|
|
||||||
|
bool pReturn = this->initWithSpriteFrame(frame, capInsets);
|
||||||
|
return pReturn;
|
||||||
|
}
|
||||||
|
|
||||||
|
Scale9Sprite* Scale9Sprite::createWithSpriteFrameName(const std::string& spriteFrameName, const Rect& capInsets)
|
||||||
|
{
|
||||||
|
Scale9Sprite* pReturn = new Scale9Sprite();
|
||||||
|
if ( pReturn && pReturn->initWithSpriteFrameName(spriteFrameName, capInsets) )
|
||||||
|
{
|
||||||
|
pReturn->autorelease();
|
||||||
|
return pReturn;
|
||||||
|
}
|
||||||
|
CC_SAFE_DELETE(pReturn);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Scale9Sprite::initWithSpriteFrameName(const std::string& spriteFrameName)
|
||||||
|
{
|
||||||
|
bool pReturn = this->initWithSpriteFrameName(spriteFrameName, Rect::ZERO);
|
||||||
|
return pReturn;
|
||||||
|
}
|
||||||
|
|
||||||
|
Scale9Sprite* Scale9Sprite::createWithSpriteFrameName(const std::string& spriteFrameName)
|
||||||
|
{
|
||||||
|
Scale9Sprite* pReturn = new Scale9Sprite();
|
||||||
|
if ( pReturn && pReturn->initWithSpriteFrameName(spriteFrameName) )
|
||||||
|
{
|
||||||
|
pReturn->autorelease();
|
||||||
|
return pReturn;
|
||||||
|
}
|
||||||
|
CC_SAFE_DELETE(pReturn);
|
||||||
|
|
||||||
|
log("Could not allocate Scale9Sprite()");
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Scale9Sprite* Scale9Sprite::resizableSpriteWithCapInsets(const Rect& capInsets)
|
||||||
|
{
|
||||||
|
Scale9Sprite* pReturn = new Scale9Sprite();
|
||||||
|
if ( pReturn && pReturn->init(_scale9Image, _spriteRect, capInsets) )
|
||||||
|
{
|
||||||
|
pReturn->autorelease();
|
||||||
|
return pReturn;
|
||||||
|
}
|
||||||
|
CC_SAFE_DELETE(pReturn);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
Scale9Sprite* Scale9Sprite::create()
|
||||||
|
{
|
||||||
|
Scale9Sprite *pReturn = new Scale9Sprite();
|
||||||
|
if (pReturn && pReturn->init())
|
||||||
|
{
|
||||||
|
pReturn->autorelease();
|
||||||
|
return pReturn;
|
||||||
|
}
|
||||||
|
CC_SAFE_DELETE(pReturn);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** sets the opacity.
|
||||||
|
@warning If the the texture has premultiplied alpha then, the R, G and B channels will be modifed.
|
||||||
|
Values goes from 0 to 255, where 255 means fully opaque.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void Scale9Sprite::updateCapInset()
|
||||||
|
{
|
||||||
|
Rect insets;
|
||||||
|
if (this->_insetLeft == 0 && this->_insetTop == 0 && this->_insetRight == 0 && this->_insetBottom == 0)
|
||||||
|
{
|
||||||
|
insets = Rect::ZERO;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
insets = Rect(_insetLeft,
|
||||||
|
_insetTop,
|
||||||
|
_spriteRect.size.width-_insetLeft-_insetRight,
|
||||||
|
_spriteRect.size.height-_insetTop-_insetBottom);
|
||||||
|
}
|
||||||
|
this->setCapInsets(insets);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Scale9Sprite::setSpriteFrame(SpriteFrame * spriteFrame)
|
||||||
|
{
|
||||||
|
Sprite * sprite = Sprite::createWithTexture(spriteFrame->getTexture());
|
||||||
|
this->updateWithSprite(sprite, spriteFrame->getRect(), spriteFrame->isRotated(), Rect::ZERO);
|
||||||
|
|
||||||
|
// Reset insets
|
||||||
|
this->_insetLeft = 0;
|
||||||
|
this->_insetTop = 0;
|
||||||
|
this->_insetRight = 0;
|
||||||
|
this->_insetBottom = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scale9Sprite::setPreferredSize(const Size& preferedSize)
|
||||||
|
{
|
||||||
|
this->setContentSize(preferedSize);
|
||||||
|
this->_preferredSize = preferedSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Scale9Sprite::setCapInsets(const Rect& capInsets)
|
||||||
|
{
|
||||||
|
Size contentSize = this->_contentSize;
|
||||||
|
this->updateWithSprite(this->_scale9Image, this->_spriteRect, _spriteFrameRotated, capInsets);
|
||||||
|
this->setContentSize(contentSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Scale9Sprite::setInsetLeft(float insetLeft)
|
||||||
|
{
|
||||||
|
this->_insetLeft = insetLeft;
|
||||||
|
this->updateCapInset();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scale9Sprite::setInsetTop(float insetTop)
|
||||||
|
{
|
||||||
|
this->_insetTop = insetTop;
|
||||||
|
this->updateCapInset();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scale9Sprite::setInsetRight(float insetRight)
|
||||||
|
{
|
||||||
|
this->_insetRight = insetRight;
|
||||||
|
this->updateCapInset();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scale9Sprite::setInsetBottom(float insetBottom)
|
||||||
|
{
|
||||||
|
this->_insetBottom = insetBottom;
|
||||||
|
this->updateCapInset();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scale9Sprite::visit(Renderer *renderer, const Mat4 &parentTransform, uint32_t parentFlags)
|
||||||
|
{
|
||||||
|
|
||||||
|
// quick return if not visible. children won't be drawn.
|
||||||
|
if (!_visible)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t flags = processParentFlags(parentTransform, parentFlags);
|
||||||
|
|
||||||
|
// IMPORTANT:
|
||||||
|
// To ease the migration to v3.0, we still support the Mat4 stack,
|
||||||
|
// but it is deprecated and your code should not rely on it
|
||||||
|
Director* director = Director::getInstance();
|
||||||
|
CCASSERT(nullptr != director, "Director is null when seting matrix stack");
|
||||||
|
director->pushMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
|
||||||
|
director->loadMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW, _modelViewTransform);
|
||||||
|
|
||||||
|
int i = 0; // used by _children
|
||||||
|
int j = 0; // used by _protectedChildren
|
||||||
|
|
||||||
|
sortAllChildren();
|
||||||
|
sortAllProtectedChildren();
|
||||||
|
|
||||||
|
//
|
||||||
|
// draw children and protectedChildren zOrder < 0
|
||||||
|
//
|
||||||
|
for( ; i < _children.size(); i++ )
|
||||||
|
{
|
||||||
|
auto node = _children.at(i);
|
||||||
|
|
||||||
|
if ( node && node->getLocalZOrder() < 0 )
|
||||||
|
node->visit(renderer, _modelViewTransform, flags);
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (_scale9Enabled) {
|
||||||
|
for( ; j < _protectedChildren.size(); j++ )
|
||||||
|
{
|
||||||
|
auto node = _protectedChildren.at(j);
|
||||||
|
|
||||||
|
if ( node && node->getLocalZOrder() < 0 )
|
||||||
|
node->visit(renderer, _modelViewTransform, flags);
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
if (_scale9Image) {
|
||||||
|
_scale9Image->visit(renderer, _modelViewTransform, flags);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// draw self
|
||||||
|
//
|
||||||
|
this->draw(renderer, _modelViewTransform, flags);
|
||||||
|
|
||||||
|
//
|
||||||
|
// draw children and protectedChildren zOrder >= 0
|
||||||
|
//
|
||||||
|
if (_scale9Enabled) {
|
||||||
|
for(auto it=_protectedChildren.cbegin()+j; it != _protectedChildren.cend(); ++it)
|
||||||
|
(*it)->visit(renderer, _modelViewTransform, flags);
|
||||||
|
}else{
|
||||||
|
if (_scale9Image) {
|
||||||
|
_scale9Image->visit(renderer, _modelViewTransform, flags);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
for(auto it=_children.cbegin()+i; it != _children.cend(); ++it)
|
||||||
|
(*it)->visit(renderer, _modelViewTransform, flags);
|
||||||
|
|
||||||
|
// reset for next frame
|
||||||
|
_orderOfArrival = 0;
|
||||||
|
|
||||||
|
director->popMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Size Scale9Sprite::getOriginalSize()const
|
||||||
|
{
|
||||||
|
return _originalSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Size Scale9Sprite::getPreferredSize() const
|
||||||
|
{
|
||||||
|
return _preferredSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
Rect Scale9Sprite::getCapInsets()const
|
||||||
|
{
|
||||||
|
return _capInsets;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
float Scale9Sprite::getInsetLeft()const
|
||||||
|
{
|
||||||
|
return this->_insetLeft;
|
||||||
|
}
|
||||||
|
|
||||||
|
float Scale9Sprite::getInsetTop()const
|
||||||
|
{
|
||||||
|
return this->_insetTop;
|
||||||
|
}
|
||||||
|
|
||||||
|
float Scale9Sprite::getInsetRight()const
|
||||||
|
{
|
||||||
|
return this->_insetRight;
|
||||||
|
}
|
||||||
|
|
||||||
|
float Scale9Sprite::getInsetBottom()const
|
||||||
|
{
|
||||||
|
return this->_insetBottom;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scale9Sprite::setScale9Enabled(bool enabled)
|
||||||
|
{
|
||||||
|
_scale9Enabled = enabled;
|
||||||
|
_reorderProtectedChildDirty = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Scale9Sprite::getScale9Enabled() const
|
||||||
|
{
|
||||||
|
return _scale9Enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scale9Sprite::addProtectedChild(cocos2d::Node *child)
|
||||||
|
{
|
||||||
|
_reorderProtectedChildDirty = true;
|
||||||
|
_protectedChildren.pushBack(child);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scale9Sprite::sortAllProtectedChildren()
|
||||||
|
{
|
||||||
|
if(this->_positionsAreDirty)
|
||||||
|
{
|
||||||
|
this->updatePositions();
|
||||||
|
this->_positionsAreDirty = false;
|
||||||
|
}
|
||||||
|
if( _reorderProtectedChildDirty ) {
|
||||||
|
if (!_scale9Enabled) {
|
||||||
|
this->adjustScale9ImagePosition();
|
||||||
|
}
|
||||||
|
std::sort( std::begin(_protectedChildren), std::end(_protectedChildren), nodeComparisonLess );
|
||||||
|
_reorderProtectedChildDirty = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scale9Sprite::adjustScale9ImagePosition()
|
||||||
|
{
|
||||||
|
if (_scale9Image) {
|
||||||
|
_scale9Image->setPosition(_scale9Image->getPosition() + Vec2(_originalSize.width/2, _originalSize.height/2));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scale9Sprite::cleanup()
|
||||||
|
{
|
||||||
|
Node::cleanup();
|
||||||
|
// timers
|
||||||
|
for( const auto &child: _protectedChildren)
|
||||||
|
child->cleanup();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scale9Sprite::onEnter()
|
||||||
|
{
|
||||||
|
#if CC_ENABLE_SCRIPT_BINDING
|
||||||
|
if (_scriptType == kScriptTypeJavascript)
|
||||||
|
{
|
||||||
|
if (ScriptEngineManager::sendNodeEventToJSExtended(this, kNodeOnEnter))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
Node::onEnter();
|
||||||
|
for( const auto &child: _protectedChildren)
|
||||||
|
child->onEnter();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scale9Sprite::onExit()
|
||||||
|
{
|
||||||
|
Node::onExit();
|
||||||
|
for( const auto &child: _protectedChildren)
|
||||||
|
child->onExit();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scale9Sprite::onEnterTransitionDidFinish()
|
||||||
|
{
|
||||||
|
Node::onEnterTransitionDidFinish();
|
||||||
|
for( const auto &child: _protectedChildren)
|
||||||
|
child->onEnterTransitionDidFinish();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scale9Sprite::onExitTransitionDidStart()
|
||||||
|
{
|
||||||
|
Node::onExitTransitionDidStart();
|
||||||
|
for( const auto &child: _protectedChildren)
|
||||||
|
child->onExitTransitionDidStart();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scale9Sprite::updateDisplayedColor(const cocos2d::Color3B &parentColor)
|
||||||
|
{
|
||||||
|
_displayedColor.r = _realColor.r * parentColor.r/255.0;
|
||||||
|
_displayedColor.g = _realColor.g * parentColor.g/255.0;
|
||||||
|
_displayedColor.b = _realColor.b * parentColor.b/255.0;
|
||||||
|
updateColor();
|
||||||
|
|
||||||
|
if (_scale9Image) {
|
||||||
|
_scale9Image->updateDisplayedColor(_displayedColor);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(const auto &child : _protectedChildren){
|
||||||
|
child->updateDisplayedColor(_displayedColor);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_cascadeColorEnabled)
|
||||||
|
{
|
||||||
|
for(const auto &child : _children){
|
||||||
|
child->updateDisplayedColor(_displayedColor);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scale9Sprite::updateDisplayedOpacity(GLubyte parentOpacity)
|
||||||
|
{
|
||||||
|
_displayedOpacity = _realOpacity * parentOpacity/255.0;
|
||||||
|
updateColor();
|
||||||
|
|
||||||
|
if (_scale9Image) {
|
||||||
|
_scale9Image->updateDisplayedOpacity(_displayedOpacity);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(auto child : _protectedChildren){
|
||||||
|
child->updateDisplayedOpacity(_displayedOpacity);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_cascadeOpacityEnabled)
|
||||||
|
{
|
||||||
|
for(auto child : _children){
|
||||||
|
child->updateDisplayedOpacity(_displayedOpacity);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scale9Sprite::disableCascadeColor()
|
||||||
|
{
|
||||||
|
for(auto child : _children){
|
||||||
|
child->updateDisplayedColor(Color3B::WHITE);
|
||||||
|
}
|
||||||
|
for(auto child : _protectedChildren){
|
||||||
|
child->updateDisplayedColor(Color3B::WHITE);
|
||||||
|
}
|
||||||
|
if (_scale9Image) {
|
||||||
|
_scale9Image->updateDisplayedColor(Color3B::WHITE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Sprite* Scale9Sprite::getSprite()const
|
||||||
|
{
|
||||||
|
return _scale9Image;
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
|
|
@ -25,6 +25,347 @@
|
||||||
#ifndef __cocos2d_libs__UIScale9Sprite__
|
#ifndef __cocos2d_libs__UIScale9Sprite__
|
||||||
#define __cocos2d_libs__UIScale9Sprite__
|
#define __cocos2d_libs__UIScale9Sprite__
|
||||||
|
|
||||||
#include <iostream>
|
#include "2d/CCNode.h"
|
||||||
|
#include "2d/CCSpriteFrame.h"
|
||||||
|
#include "2d/CCSpriteBatchNode.h"
|
||||||
|
#include "base/CCPlatformMacros.h"
|
||||||
|
|
||||||
|
NS_CC_BEGIN
|
||||||
|
namespace ui {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A 9-slice sprite for cocos2d.
|
||||||
|
*
|
||||||
|
* 9-slice scaling allows you to specify how scaling is applied
|
||||||
|
* to specific areas of a sprite. With 9-slice scaling (3x3 grid),
|
||||||
|
* you can ensure that the sprite does not become distorted when
|
||||||
|
* scaled.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
class Scale9Sprite : public Node
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* @js ctor
|
||||||
|
*/
|
||||||
|
Scale9Sprite();
|
||||||
|
/**
|
||||||
|
* @js NA
|
||||||
|
* @lua NA
|
||||||
|
*/
|
||||||
|
virtual ~Scale9Sprite();
|
||||||
|
|
||||||
|
public:
|
||||||
|
static Scale9Sprite* create();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a 9-slice sprite with a texture file, a delimitation zone and
|
||||||
|
* with the specified cap insets.
|
||||||
|
*
|
||||||
|
* @see initWithFile(const char *file, const Rect& rect, const Rect& capInsets)
|
||||||
|
*/
|
||||||
|
static Scale9Sprite* create(const std::string& file, const Rect& rect, const Rect& capInsets);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a 9-slice sprite with a texture file. The whole texture will be
|
||||||
|
* broken down into a 3×3 grid of equal blocks.
|
||||||
|
*
|
||||||
|
* @see initWithFile(const Rect& capInsets, const char *file)
|
||||||
|
*/
|
||||||
|
static Scale9Sprite* create(const Rect& capInsets, const std::string& file);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a 9-slice sprite with a texture file and a delimitation zone. The
|
||||||
|
* texture will be broken down into a 3×3 grid of equal blocks.
|
||||||
|
*
|
||||||
|
* @see initWithFile(const char *file, const Rect& rect)
|
||||||
|
*/
|
||||||
|
static Scale9Sprite* create(const std::string& file, const Rect& rect);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a 9-slice sprite with a texture file. The whole texture will be
|
||||||
|
* broken down into a 3×3 grid of equal blocks.
|
||||||
|
*
|
||||||
|
* @see initWithFile(const char *file)
|
||||||
|
*/
|
||||||
|
static Scale9Sprite* create(const std::string& file);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a 9-slice sprite with an sprite frame.
|
||||||
|
* Once the sprite is created, you can then call its "setContentSize:" method
|
||||||
|
* to resize the sprite will all it's 9-slice goodness intract.
|
||||||
|
* It respects the anchorPoint too.
|
||||||
|
*
|
||||||
|
* @see initWithSpriteFrame(SpriteFrame *spriteFrame)
|
||||||
|
*/
|
||||||
|
static Scale9Sprite* createWithSpriteFrame(SpriteFrame* spriteFrame);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a 9-slice sprite with an sprite frame and the centre of its zone.
|
||||||
|
* Once the sprite is created, you can then call its "setContentSize:" method
|
||||||
|
* to resize the sprite will all it's 9-slice goodness intract.
|
||||||
|
* It respects the anchorPoint too.
|
||||||
|
*
|
||||||
|
* @see initWithSpriteFrame(SpriteFrame *spriteFrame, const Rect& capInsets)
|
||||||
|
*/
|
||||||
|
static Scale9Sprite* createWithSpriteFrame(SpriteFrame* spriteFrame, const Rect& capInsets);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a 9-slice sprite with an sprite frame name.
|
||||||
|
* Once the sprite is created, you can then call its "setContentSize:" method
|
||||||
|
* to resize the sprite will all it's 9-slice goodness intract.
|
||||||
|
* It respects the anchorPoint too.
|
||||||
|
*
|
||||||
|
* @see initWithSpriteFrameName(const char *spriteFrameName)
|
||||||
|
*/
|
||||||
|
static Scale9Sprite* createWithSpriteFrameName(const std::string& spriteFrameName);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a 9-slice sprite with an sprite frame name and the centre of its
|
||||||
|
* zone.
|
||||||
|
* Once the sprite is created, you can then call its "setContentSize:" method
|
||||||
|
* to resize the sprite will all it's 9-slice goodness intract.
|
||||||
|
* It respects the anchorPoint too.
|
||||||
|
*
|
||||||
|
* @see initWithSpriteFrameName(const char *spriteFrameName, const Rect& capInsets)
|
||||||
|
*/
|
||||||
|
static Scale9Sprite* createWithSpriteFrameName(const std::string& spriteFrameName, const Rect& capInsets);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes a 9-slice sprite with a texture file, a delimitation zone and
|
||||||
|
* with the specified cap insets.
|
||||||
|
* Once the sprite is created, you can then call its "setContentSize:" method
|
||||||
|
* to resize the sprite will all it's 9-slice goodness intract.
|
||||||
|
* It respects the anchorPoint too.
|
||||||
|
*
|
||||||
|
* @param file The name of the texture file.
|
||||||
|
* @param rect The rectangle that describes the sub-part of the texture that
|
||||||
|
* is the whole image. If the shape is the whole texture, set this to the
|
||||||
|
* texture's full rect.
|
||||||
|
* @param capInsets The values to use for the cap insets.
|
||||||
|
*/
|
||||||
|
virtual bool initWithFile(const std::string& file, const Rect& rect, const Rect& capInsets);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes a 9-slice sprite with a texture file and a delimitation zone. The
|
||||||
|
* texture will be broken down into a 3×3 grid of equal blocks.
|
||||||
|
* Once the sprite is created, you can then call its "setContentSize:" method
|
||||||
|
* to resize the sprite will all it's 9-slice goodness intract.
|
||||||
|
* It respects the anchorPoint too.
|
||||||
|
*
|
||||||
|
* @param file The name of the texture file.
|
||||||
|
* @param rect The rectangle that describes the sub-part of the texture that
|
||||||
|
* is the whole image. If the shape is the whole texture, set this to the
|
||||||
|
* texture's full rect.
|
||||||
|
*/
|
||||||
|
virtual bool initWithFile(const std::string& file, const Rect& rect);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes a 9-slice sprite with a texture file and with the specified cap
|
||||||
|
* insets.
|
||||||
|
* Once the sprite is created, you can then call its "setContentSize:" method
|
||||||
|
* to resize the sprite will all it's 9-slice goodness intract.
|
||||||
|
* It respects the anchorPoint too.
|
||||||
|
*
|
||||||
|
* @param file The name of the texture file.
|
||||||
|
* @param capInsets The values to use for the cap insets.
|
||||||
|
*/
|
||||||
|
virtual bool initWithFile(const Rect& capInsets, const std::string& file);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes a 9-slice sprite with a texture file. The whole texture will be
|
||||||
|
* broken down into a 3×3 grid of equal blocks.
|
||||||
|
* Once the sprite is created, you can then call its "setContentSize:" method
|
||||||
|
* to resize the sprite will all it's 9-slice goodness intract.
|
||||||
|
* It respects the anchorPoint too.
|
||||||
|
*
|
||||||
|
* @param file The name of the texture file.
|
||||||
|
*/
|
||||||
|
virtual bool initWithFile(const std::string& file);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes a 9-slice sprite with an sprite frame and with the specified
|
||||||
|
* cap insets.
|
||||||
|
* Once the sprite is created, you can then call its "setContentSize:" method
|
||||||
|
* to resize the sprite will all it's 9-slice goodness intract.
|
||||||
|
* It respects the anchorPoint too.
|
||||||
|
*
|
||||||
|
* @param spriteFrame The sprite frame object.
|
||||||
|
* @param capInsets The values to use for the cap insets.
|
||||||
|
*/
|
||||||
|
virtual bool initWithSpriteFrame(SpriteFrame* spriteFrame, const Rect& capInsets);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes a 9-slice sprite with an sprite frame.
|
||||||
|
* Once the sprite is created, you can then call its "setContentSize:" method
|
||||||
|
* to resize the sprite will all it's 9-slice goodness intract.
|
||||||
|
* It respects the anchorPoint too.
|
||||||
|
*
|
||||||
|
* @param spriteFrame The sprite frame object.
|
||||||
|
*/
|
||||||
|
virtual bool initWithSpriteFrame(SpriteFrame* spriteFrame);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes a 9-slice sprite with an sprite frame name and with the specified
|
||||||
|
* cap insets.
|
||||||
|
* Once the sprite is created, you can then call its "setContentSize:" method
|
||||||
|
* to resize the sprite will all it's 9-slice goodness intract.
|
||||||
|
* It respects the anchorPoint too.
|
||||||
|
*
|
||||||
|
* @param spriteFrameName The sprite frame name.
|
||||||
|
* @param capInsets The values to use for the cap insets.
|
||||||
|
*/
|
||||||
|
virtual bool initWithSpriteFrameName(const std::string& spriteFrameName, const Rect& capInsets);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes a 9-slice sprite with an sprite frame name.
|
||||||
|
* Once the sprite is created, you can then call its "setContentSize:" method
|
||||||
|
* to resize the sprite will all it's 9-slice goodness intract.
|
||||||
|
* It respects the anchorPoint too.
|
||||||
|
*
|
||||||
|
* @param spriteFrameName The sprite frame name.
|
||||||
|
*/
|
||||||
|
virtual bool initWithSpriteFrameName(const std::string& spriteFrameName);
|
||||||
|
|
||||||
|
virtual bool init();
|
||||||
|
virtual bool init(Sprite* sprite, const Rect& rect, bool rotated, const Rect& capInsets);
|
||||||
|
virtual bool init(Sprite* sprite, const Rect& rect, const Rect& capInsets);
|
||||||
|
/**
|
||||||
|
* Creates and returns a new sprite object with the specified cap insets.
|
||||||
|
* You use this method to add cap insets to a sprite or to change the existing
|
||||||
|
* cap insets of a sprite. In both cases, you get back a new image and the
|
||||||
|
* original sprite remains untouched.
|
||||||
|
*
|
||||||
|
* @param capInsets The values to use for the cap insets.
|
||||||
|
*/
|
||||||
|
Scale9Sprite* resizableSpriteWithCapInsets(const Rect& capInsets);
|
||||||
|
|
||||||
|
virtual bool updateWithSprite(Sprite* sprite, const Rect& rect, bool rotated, const Rect& capInsets);
|
||||||
|
virtual void setSpriteFrame(SpriteFrame * spriteFrame);
|
||||||
|
|
||||||
|
// overrides
|
||||||
|
virtual void setContentSize(const Size & size) override;
|
||||||
|
|
||||||
|
|
||||||
|
Size getOriginalSize() const;
|
||||||
|
void setPreferredSize(const Size& size);
|
||||||
|
Size getPreferredSize() const;
|
||||||
|
void setCapInsets(const Rect& rect);
|
||||||
|
Rect getCapInsets()const;
|
||||||
|
void setInsetLeft(float leftInset);
|
||||||
|
float getInsetLeft()const;
|
||||||
|
void setInsetTop(float topInset);
|
||||||
|
float getInsetTop()const;
|
||||||
|
void setInsetRight(float rightInset);
|
||||||
|
float getInsetRight()const;
|
||||||
|
void setInsetBottom(float bottomInset);
|
||||||
|
float getInsetBottom()const;
|
||||||
|
void setScale9Enabled(bool enabled);
|
||||||
|
bool getScale9Enabled()const;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/// @} end of Children and Parent
|
||||||
|
|
||||||
|
virtual void visit(Renderer *renderer, const Mat4 &parentTransform, uint32_t parentFlags) override;
|
||||||
|
|
||||||
|
virtual void cleanup() override;
|
||||||
|
|
||||||
|
virtual void onEnter() override;
|
||||||
|
|
||||||
|
/** Event callback that is invoked when the Node enters in the 'stage'.
|
||||||
|
* If the Node enters the 'stage' with a transition, this event is called when the transition finishes.
|
||||||
|
* If you override onEnterTransitionDidFinish, you shall call its parent's one, e.g. Node::onEnterTransitionDidFinish()
|
||||||
|
* @js NA
|
||||||
|
* @lua NA
|
||||||
|
*/
|
||||||
|
virtual void onEnterTransitionDidFinish() override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Event callback that is invoked every time the Node leaves the 'stage'.
|
||||||
|
* If the Node leaves the 'stage' with a transition, this event is called when the transition finishes.
|
||||||
|
* During onExit you can't access a sibling node.
|
||||||
|
* If you override onExit, you shall call its parent's one, e.g., Node::onExit().
|
||||||
|
* @js NA
|
||||||
|
* @lua NA
|
||||||
|
*/
|
||||||
|
virtual void onExit() override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Event callback that is called every time the Node leaves the 'stage'.
|
||||||
|
* If the Node leaves the 'stage' with a transition, this callback is called when the transition starts.
|
||||||
|
* @js NA
|
||||||
|
* @lua NA
|
||||||
|
*/
|
||||||
|
virtual void onExitTransitionDidStart() override;
|
||||||
|
|
||||||
|
virtual void updateDisplayedOpacity(GLubyte parentOpacity) override;
|
||||||
|
virtual void updateDisplayedColor(const Color3B& parentColor) override;
|
||||||
|
virtual void disableCascadeColor() override;
|
||||||
|
|
||||||
|
Sprite* getSprite()const;
|
||||||
|
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void updateCapInset();
|
||||||
|
void updatePositions();
|
||||||
|
void createSlicedSprites(const Rect& rect, bool rotated);
|
||||||
|
void cleanupSlicedSprites();
|
||||||
|
void adjustScale9ImagePosition();
|
||||||
|
/**
|
||||||
|
* Sorts the children array once before drawing, instead of every time when a child is added or reordered.
|
||||||
|
* This appraoch can improves the performance massively.
|
||||||
|
* @note Don't call this manually unless a child added needs to be removed in the same frame
|
||||||
|
*/
|
||||||
|
virtual void sortAllProtectedChildren();
|
||||||
|
|
||||||
|
bool _spritesGenerated;
|
||||||
|
Rect _spriteRect;
|
||||||
|
bool _spriteFrameRotated;
|
||||||
|
Rect _capInsetsInternal;
|
||||||
|
bool _positionsAreDirty;
|
||||||
|
|
||||||
|
Sprite* _scale9Image; //the original sprite
|
||||||
|
Sprite* _topLeft;
|
||||||
|
Sprite* _top;
|
||||||
|
Sprite* _topRight;
|
||||||
|
Sprite* _left;
|
||||||
|
Sprite* _centre;
|
||||||
|
Sprite* _right;
|
||||||
|
Sprite* _bottomLeft;
|
||||||
|
Sprite* _bottom;
|
||||||
|
Sprite* _bottomRight;
|
||||||
|
|
||||||
|
bool _scale9Enabled;
|
||||||
|
|
||||||
|
/** Original sprite's size. */
|
||||||
|
Size _originalSize;
|
||||||
|
/** Prefered sprite's size. By default the prefered size is the original size. */
|
||||||
|
|
||||||
|
//if the preferredSize component is given as -1, it is ignored
|
||||||
|
Size _preferredSize;
|
||||||
|
/**
|
||||||
|
* The end-cap insets.
|
||||||
|
* On a non-resizeable sprite, this property is set to CGRect::ZERO; the sprite
|
||||||
|
* does not use end caps and the entire sprite is subject to stretching.
|
||||||
|
*/
|
||||||
|
Rect _capInsets;
|
||||||
|
/** Sets the left side inset */
|
||||||
|
float _insetLeft;
|
||||||
|
/** Sets the top side inset */
|
||||||
|
float _insetTop;
|
||||||
|
/** Sets the right side inset */
|
||||||
|
float _insetRight;
|
||||||
|
/** Sets the bottom side inset */
|
||||||
|
float _insetBottom;
|
||||||
|
|
||||||
|
/// helper that reorder a child
|
||||||
|
void addProtectedChild(Node* child);
|
||||||
|
|
||||||
|
Vector<Node*> _protectedChildren; ///holds the 9 sprites
|
||||||
|
bool _reorderProtectedChildDirty;
|
||||||
|
};
|
||||||
|
|
||||||
|
}} //end of namespace
|
||||||
|
|
||||||
#endif /* defined(__cocos2d_libs__UIScale9Sprite__) */
|
#endif /* defined(__cocos2d_libs__UIScale9Sprite__) */
|
||||||
|
|
Loading…
Reference in New Issue