diff --git a/cocos2dx/extensions/CCControlExtension/CCScale9Sprite.cpp b/cocos2dx/extensions/CCControlExtension/CCScale9Sprite.cpp index 220a198119..e8fc1358e0 100644 --- a/cocos2dx/extensions/CCControlExtension/CCScale9Sprite.cpp +++ b/cocos2dx/extensions/CCControlExtension/CCScale9Sprite.cpp @@ -25,12 +25,50 @@ CCScale9Sprite::~CCScale9Sprite() } +bool CCScale9Sprite::init() +{ + return this->initWithBatchNode(NULL, CCRectZero, CCRectZero); +} + bool CCScale9Sprite::initWithBatchNode(CCSpriteBatchNode* batchnode, CCRect rect, CCRect capInsets) { + if(batchnode) + { + this->updateWithBatchNode(batchnode, rect, capInsets); + this->setAnchorPoint(ccp(0.5f,0.5f)); + } + this->m_positionsAreDirty = true; - CCAssert(batchnode != NULL, "The batchnode must be not nil."); + return this; +} + +bool CCScale9Sprite::updateWithBatchNode(CCSpriteBatchNode* batchnode, CCRect rect, CCRect capInsets) +{ + // Release old sprites + this->removeAllChildrenWithCleanup(true); + + if(this->topLeft) + { + CC_SAFE_RELEASE(this->topLeft); + CC_SAFE_RELEASE(this->top); + CC_SAFE_RELEASE(this->topRight); + CC_SAFE_RELEASE(this->left); + CC_SAFE_RELEASE(this->centre); + CC_SAFE_RELEASE(this->right); + CC_SAFE_RELEASE(this->bottomLeft); + CC_SAFE_RELEASE(this->bottom); + CC_SAFE_RELEASE(this->bottomRight); + } - scale9Image = batchnode; + if(this->scale9Image != batchnode) + { + CC_SAFE_RELEASE(this->scale9Image); + scale9Image = batchnode; // TODO No retain on purpose? + } + + scale9Image->removeAllChildrenWithCleanup(true); + + m_capInsets = capInsets; // If there is no given rect if ( CCRect::CCRectEqualToRect(rect, CCRectZero) ) @@ -45,14 +83,14 @@ bool CCScale9Sprite::initWithBatchNode(CCSpriteBatchNode* batchnode, CCRect rect m_spriteRect = rect; m_originalSize = rect.size; m_preferredSize = m_originalSize; - m_capInsets = capInsets; + m_capInsetsInternal = capInsets; this->setAnchorPoint(ccp(0.5f, 0.5f)); // If there is no specified center region - if ( CCRect::CCRectEqualToRect(m_capInsets, CCRectZero) ) + if ( CCRect::CCRectEqualToRect(m_capInsetsInternal, CCRectZero) ) { // Apply the 3x3 grid format - m_capInsets = CCRectMake( + m_capInsetsInternal = CCRectMake( rect.origin.x + m_originalSize.width / 3, rect.origin.y + m_originalSize.height / 3, m_originalSize.width / 3, @@ -70,71 +108,71 @@ bool CCScale9Sprite::initWithBatchNode(CCSpriteBatchNode* batchnode, CCRect rect // // Centre - centre = CCSprite::spriteWithTexture(scale9Image->getTexture(), m_capInsets); + centre = CCSprite::spriteWithTexture(scale9Image->getTexture(), m_capInsetsInternal); scale9Image->addChild(centre ,0 ,pCentre); // Top - top = CCSprite::spriteWithTexture(scale9Image->getTexture(), CCRectMake(m_capInsets.origin.x, + top = CCSprite::spriteWithTexture(scale9Image->getTexture(), CCRectMake(m_capInsetsInternal.origin.x, t, - m_capInsets.size.width, - m_capInsets.origin.y - t)); + m_capInsetsInternal.size.width, + m_capInsetsInternal.origin.y - t)); scale9Image->addChild(top, 1, pTop); // Bottom - bottom = CCSprite::spriteWithTexture(scale9Image->getTexture(), CCRectMake( m_capInsets.origin.x, - m_capInsets.origin.y + m_capInsets.size.height, - m_capInsets.size.width, - h - (m_capInsets.origin.y - t + m_capInsets.size.height) )); + bottom = CCSprite::spriteWithTexture(scale9Image->getTexture(), CCRectMake( m_capInsetsInternal.origin.x, + m_capInsetsInternal.origin.y + m_capInsetsInternal.size.height, + m_capInsetsInternal.size.width, + h - (m_capInsetsInternal.origin.y - t + m_capInsetsInternal.size.height) )); scale9Image->addChild(bottom, 1, pBottom); // Left left = CCSprite::spriteWithTexture(scale9Image->getTexture(), CCRectMake( l, - m_capInsets.origin.y, - m_capInsets.origin.x - l, - m_capInsets.size.height) ); + m_capInsetsInternal.origin.y, + m_capInsetsInternal.origin.x - l, + m_capInsetsInternal.size.height) ); scale9Image->addChild(left, 1, pLeft); // Right right = CCSprite::spriteWithTexture(scale9Image->getTexture(), CCRectMake( - m_capInsets.origin.x + m_capInsets.size.width, - m_capInsets.origin.y, - w - (m_capInsets.origin.x - l + m_capInsets.size.width), - m_capInsets.size.height)); + m_capInsetsInternal.origin.x + m_capInsetsInternal.size.width, + m_capInsetsInternal.origin.y, + w - (m_capInsetsInternal.origin.x - l + m_capInsetsInternal.size.width), + m_capInsetsInternal.size.height)); scale9Image->addChild(right, 1, pRight); // Top left topLeft = CCSprite::spriteWithTexture(scale9Image->getTexture(), CCRectMake( l, t, - m_capInsets.origin.x - l, - m_capInsets.origin.y - t)); + m_capInsetsInternal.origin.x - l, + m_capInsetsInternal.origin.y - t)); scale9Image->addChild(topLeft, 2, pTopLeft); // Top right topRight = CCSprite::spriteWithTexture(scale9Image->getTexture(), CCRectMake( - m_capInsets.origin.x + m_capInsets.size.width, + m_capInsetsInternal.origin.x + m_capInsetsInternal.size.width, t, - w - (m_capInsets.origin.x - l + m_capInsets.size.width), - m_capInsets.origin.y - t)); + w - (m_capInsetsInternal.origin.x - l + m_capInsetsInternal.size.width), + m_capInsetsInternal.origin.y - t)); scale9Image->addChild(topRight, 2, pTopRight); // Bottom left bottomLeft = CCSprite::spriteWithTexture(scale9Image->getTexture(), CCRectMake( l, - m_capInsets.origin.y + m_capInsets.size.height, - m_capInsets.origin.x - l, - h - (m_capInsets.origin.y - t + m_capInsets.size.height)) ); + m_capInsetsInternal.origin.y + m_capInsetsInternal.size.height, + m_capInsetsInternal.origin.x - l, + h - (m_capInsetsInternal.origin.y - t + m_capInsetsInternal.size.height)) ); scale9Image->addChild(bottomLeft, 2, pBottomLeft); // Bottom right bottomRight = CCSprite::spriteWithTexture(scale9Image->getTexture(), CCRectMake( - m_capInsets.origin.x + m_capInsets.size.width, - m_capInsets.origin.y + m_capInsets.size.height, - w - (m_capInsets.origin.x - l + m_capInsets.size.width), - h - (m_capInsets.origin.y - t + m_capInsets.size.height)) ); + m_capInsetsInternal.origin.x + m_capInsetsInternal.size.width, + m_capInsetsInternal.origin.y + m_capInsetsInternal.size.height, + w - (m_capInsetsInternal.origin.x - l + m_capInsetsInternal.size.width), + h - (m_capInsetsInternal.origin.y - t + m_capInsetsInternal.size.height)) ); scale9Image->addChild(bottomRight, 2, pBottomRight); @@ -146,13 +184,17 @@ bool CCScale9Sprite::initWithBatchNode(CCSpriteBatchNode* batchnode, CCRect rect void CCScale9Sprite::setContentSize(const CCSize &size) { - CCNode::setContentSize(size); - setAnchorPoint(ccp(0.5f,0.5f)); - + this->m_positionsAreDirty = true; +} + +void CCScale9Sprite::updatePositions() +{ + CCSize size = this->m_tContentSize; + CCLOG("scale9 set content size %0.2f %0.2f",size.width,size.height); CCLOG("leftCap %0.2f rightCap %0.2f",topLeft->getContentSize().width,topRight->getContentSize().width); - + 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; @@ -161,27 +203,39 @@ void CCScale9Sprite::setContentSize(const CCSize &size) centre->setScaleY(verticalScale); float rescaledWidth = centre->getContentSize().width * horizontalScale; float rescaledHeight = centre->getContentSize().height * verticalScale; - - float despx = size.width*0.5f; - float despy = size.height*0.5f; - - //Position corners - topLeft->setPosition(ccp(-rescaledWidth/2 - topLeft->getContentSize().width/2 +despx, rescaledHeight/2 + topLeft->getContentSize().height*0.5f +despy) ); - topRight->setPosition(ccp(rescaledWidth/2 + topRight->getContentSize().width/2 +despx, rescaledHeight/2 + topRight->getContentSize().height*0.5f +despy)); - bottomLeft->setPosition(ccp(-rescaledWidth/2 - bottomLeft->getContentSize().width/2 +despx, -rescaledHeight/2 - bottomLeft->getContentSize().height*0.5f +despy)); - bottomRight->setPosition(ccp(rescaledWidth/2 + bottomRight->getContentSize().width/2 +despx, -rescaledHeight/2 + -bottomRight->getContentSize().height*0.5f +despy)); - + + float leftWidth = bottomLeft->getContentSize().width; + float bottomHeight = bottomLeft->getContentSize().height; + + bottomLeft->setAnchorPoint(ccp(0,0)); + bottomRight->setAnchorPoint(ccp(0,0)); + topLeft->setAnchorPoint(ccp(0,0)); + topRight->setAnchorPoint(ccp(0,0)); + left->setAnchorPoint(ccp(0,0)); + right->setAnchorPoint(ccp(0,0)); + top->setAnchorPoint(ccp(0,0)); + bottom->setAnchorPoint(ccp(0,0)); + centre->setAnchorPoint(ccp(0,0)); + + // Position corners + bottomLeft->setPosition(ccp(0,0)); + bottomRight->setPosition(ccp(leftWidth+rescaledWidth,0)); + topLeft->setPosition(ccp(0, bottomHeight+rescaledHeight)); + topRight->setPosition(ccp(leftWidth+rescaledWidth, bottomHeight+rescaledHeight)); + + // Scale and position borders + left->setPosition(ccp(0, bottomHeight)); + left->setScaleY(verticalScale); + right->setPosition(ccp(leftWidth+rescaledWidth,bottomHeight)); + right->setScaleY(verticalScale); + bottom->setPosition(ccp(leftWidth,0)); + bottom->setScaleX(horizontalScale); + top->setPosition(ccp(leftWidth,bottomHeight+rescaledHeight)); top->setScaleX(horizontalScale); - top->setPosition(ccp(0+despx,rescaledHeight/2 + topLeft->getContentSize().height*0.5f +despy)); - bottom->setScaleX (horizontalScale); - bottom->setPosition(ccp(0+despx,-rescaledHeight/2 - bottomLeft->getContentSize().height*0.5f +despy)); - left->setScaleY (verticalScale); - left->setPosition(ccp(-rescaledWidth/2 - topLeft->getContentSize().width/2 +despx, 0+despy)); - right->setScaleY (verticalScale); - right->setPosition(ccp(rescaledWidth/2 + topRight->getContentSize().width/2 +despx, 0+despy)); - - centre->setPosition(ccp(despx, despy)); - + + // Position centre + centre->setPosition(ccp(leftWidth, bottomHeight)); + CCLOG("Scale9 setContentSize %02.f x %02.f <%0.2f x %0.2f>",sizableWidth,sizableHeight,horizontalScale,verticalScale); } @@ -263,7 +317,7 @@ CCScale9Sprite* CCScale9Sprite::spriteWithFile(const char* file) bool CCScale9Sprite::initWithSpriteFrame(CCSpriteFrame* spriteFrame, CCRect capInsets) { CCAssert(spriteFrame != NULL, "Sprite frame must be not nil"); - + CCSpriteBatchNode *batchnode = CCSpriteBatchNode::batchNodeWithTexture(spriteFrame->getTexture(), 9); bool pReturn = this->initWithBatchNode(batchnode, spriteFrame->getRect(), capInsets); return pReturn; @@ -301,7 +355,7 @@ CCScale9Sprite* CCScale9Sprite::spriteWithSpriteFrame(CCSpriteFrame* spriteFrame bool CCScale9Sprite::initWithSpriteFrameName(const char* spriteFrameName, CCRect capInsets) { CCAssert(spriteFrameName != NULL, "Invalid spriteFrameName for sprite"); - + CCSpriteFrame *frame = CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName(spriteFrameName); bool pReturn = this->initWithSpriteFrame(frame, capInsets); return pReturn; @@ -317,7 +371,6 @@ CCScale9Sprite* CCScale9Sprite::spriteWithSpriteFrameName(const char* spriteFram } CC_SAFE_DELETE(pReturn); return NULL; - } bool CCScale9Sprite::initWithSpriteFrameName(const char* spriteFrameName) @@ -387,7 +440,7 @@ const ccColor3B& CCScale9Sprite::getColor(void) void CCScale9Sprite::setOpacity(GLubyte var) { m_cOpacity = var; - + if (scale9Image->getChildren() && scale9Image->getChildren()->count() != 0) { CCObject* child; @@ -420,10 +473,22 @@ GLubyte CCScale9Sprite::getOpacity() return m_cOpacity; } +void CCScale9Sprite::setPreferredSize(CCSize preferedSize) +{ + this->setContentSize(preferedSize); + this->m_preferredSize = preferedSize; +} + +CCSize CCScale9Sprite::getPreferredSize() +{ + return this->m_preferredSize; +} void CCScale9Sprite::setCapInsets(CCRect capInsets) { - m_capInsets = capInsets; + CCSize contentSize = this->m_tContentSize; + this->updateWithBatchNode(this->scale9Image, this->m_spriteRect, capInsets); + this->setContentSize(contentSize); } CCRect CCScale9Sprite::getCapInsets() @@ -431,6 +496,23 @@ CCRect CCScale9Sprite::getCapInsets() return m_capInsets; } +void CCScale9Sprite::updateCapInset() +{ + CCRect insets; + if (this->m_insetLeft == 0 && this->m_insetTop == 0 && this->m_insetRight == 0 && this->m_insetBottom == 0) + { + insets = CCRectZero; + } + else + { + insets = CCRectMake(this->m_insetLeft, + this->m_insetTop, + this->m_spriteRect.size.width-this->m_insetLeft-this->m_insetRight, + this->m_spriteRect.size.height-this->m_insetTop-this->m_insetBottom); + } + this->setCapInsets(insets); +} + void CCScale9Sprite::setIsOpacityModifyRGB(bool var) { m_bIsOpacityModifyRGB = var; @@ -461,4 +543,70 @@ bool CCScale9Sprite::getIsOpacityModifyRGB() return m_bIsOpacityModifyRGB; } +void CCScale9Sprite::setSpriteFrame(CCSpriteFrame * spriteFrame) +{ + CCSpriteBatchNode * batchnode = CCSpriteBatchNode::batchNodeWithTexture(spriteFrame->getTexture(), 9); + this->updateWithBatchNode(batchnode, spriteFrame->getRect(), CCRectZero); + + // Reset insets + this->m_insetLeft = 0; + this->m_insetTop = 0; + this->m_insetRight = 0; + this->m_insetBottom = 0; +} + +float CCScale9Sprite::getInsetLeft() +{ + return this->m_insetLeft; +} + +float CCScale9Sprite::getInsetTop() +{ + return this->m_insetTop; +} + +float CCScale9Sprite::getInsetRight() +{ + return this->m_insetRight; +} + +float CCScale9Sprite::getInsetBottom() +{ + return this->m_insetBottom; +} + +void CCScale9Sprite::setInsetLeft(float insetLeft) +{ + this->m_insetLeft = insetLeft; + this->updateCapInset(); +} + +void CCScale9Sprite::setInsetTop(float insetTop) +{ + this->m_insetTop = insetTop; + this->updateCapInset(); +} + +void CCScale9Sprite::setInsetRight(float insetRight) +{ + this->m_insetRight = insetRight; + this->updateCapInset(); +} + +void CCScale9Sprite::setInsetBottom(float insetBottom) +{ + this->m_insetBottom = insetBottom; + this->updateCapInset(); +} + +void CCScale9Sprite::visit() +{ + if(this->m_positionsAreDirty) + { + this->updatePositions(); + this->m_positionsAreDirty = false; + } + CCNode::visit(); +} + NS_CC_EXT_END diff --git a/cocos2dx/extensions/CCControlExtension/CCScale9Sprite.h b/cocos2dx/extensions/CCControlExtension/CCScale9Sprite.h index 7b912463f1..6c5938e3d6 100644 --- a/cocos2dx/extensions/CCControlExtension/CCScale9Sprite.h +++ b/cocos2dx/extensions/CCControlExtension/CCScale9Sprite.h @@ -44,7 +44,7 @@ public: /** Prefered sprite's size. By default the prefered size is the original size. */ //if the preferredSize component is given as -1, it is ignored - CC_SYNTHESIZE(CCSize, m_preferredSize, PreferredSize); + CC_PROPERTY(CCSize, m_preferredSize, PreferredSize); /** * The end-cap insets. * On a non-resizeable sprite, this property is set to CGRectZero; the sprite @@ -56,10 +56,15 @@ public: /** Color: conforms to CCRGBAProtocol protocol */ CC_PROPERTY_PASS_BY_REF(ccColor3B, m_tColor, Color) CC_PROPERTY(CCRect, m_capInsets, CapInsets); - + CC_PROPERTY(float, m_insetLeft, InsetLeft); + CC_PROPERTY(float, m_insetTop, InsetTop); + CC_PROPERTY(float, m_insetRight, InsetRight); + CC_PROPERTY(float, m_insetBottom, InsetBottom); protected: CCRect m_spriteRect; + CCRect m_capInsetsInternal; + bool m_positionsAreDirty; CCSpriteBatchNode* scale9Image; CCSprite* topLeft; @@ -75,11 +80,17 @@ protected: /** Conforms to CocosNodeRGBA protocol. */ ccColor3B m_sColorUnmodified; bool m_bIsOpacityModifyRGB; - + + void updateCapInset(); + void updatePositions(); + public: - void virtual setContentSize(const CCSize &size); + virtual void setContentSize(const CCSize &size); + virtual void visit(); + virtual bool init(); + virtual bool initWithBatchNode(CCSpriteBatchNode* batchnode, CCRect rect, CCRect capInsets); /** * Initializes a 9-slice sprite with a texture file, a delimitation zone and @@ -273,7 +284,10 @@ public: @since v0.8 */ virtual bool getIsOpacityModifyRGB(void); - + + virtual bool updateWithBatchNode(CCSpriteBatchNode* batchnode, CCRect rect, CCRect capInsets); + + virtual void setSpriteFrame(CCSpriteFrame * spriteFrame); }; NS_CC_EXT_END