I have a situation where I want to swap the normal and highlighted background sprites of a button. I tried a direct swap
CCScale9Sprite* hSprt = nAsBtn->getBackgroundSpriteForState(CCControlStateHighlighted);
CCScale9Sprite* nSprt = nAsBtn->getBackgroundSpriteForState(CCControlStateNormal);
nSprt->retain();
nAsBtn->setBackgroundSpriteForState(hSprt, CCControlStateNormal);
nAsBtn->setBackgroundSpriteForState(nSprt, CCControlStateHighlighted);
nSprt->release();
I got an error that the sprite was already a child, so I tried retain/remove/set/release each sprite, but this crashed because sending NULL to getBackgroundSpriteForState crashes when trying to add it to m_backgroundSpriteDispatchTable. I decided to fix both issues:
CCCONTROLBUTTON.CPP FIX:
void CCControlButton::setBackgroundSpriteForState(CCScale9Sprite* sprite, CCControlState state)
{
CCSize oldPreferredSize = m_preferredSize;
CCScale9Sprite* previousBackgroundSprite = (CCScale9Sprite*)m_backgroundSpriteDispatchTable->objectForKey(state);
if (previousBackgroundSprite)
{
m_backgroundSpriteDispatchTable->removeObjectForKey(state);
// remove previous sprite if not in another state
if ((previousBackgroundSprite != m_backgroundSpriteDispatchTable->objectForKey(CCControlStateNormal)) &&
(previousBackgroundSprite != m_backgroundSpriteDispatchTable->objectForKey(CCControlStateDisabled)) &&
(previousBackgroundSprite != m_backgroundSpriteDispatchTable->objectForKey(CCControlStateHighlighted)) &&
(previousBackgroundSprite != m_backgroundSpriteDispatchTable->objectForKey(CCControlStateSelected)))
removeChild(previousBackgroundSprite, true);
}
if (sprite != NULL ) { // skip adding if sprite is NULL
m_backgroundSpriteDispatchTable->setObject(sprite, state);
sprite->setVisible(false);
sprite->setAnchorPoint(ccp(0.5f, 0.5f));
if (this != sprite->getParent()) addChild(sprite); // must check if sprite already a child before adding
if (this->m_preferredSize.width != 0 || this->m_preferredSize.height != 0)
{
if (oldPreferredSize.equals(m_preferredSize))
{
// Force update of preferred size
sprite->setPreferredSize(CCSizeMake(oldPreferredSize.width+1, oldPreferredSize.height+1));
}
sprite->setPreferredSize(this->m_preferredSize);
}
}
// If the current state if equal to the given state we update the layout
if (getState() == state)
{
needsLayout();
}
}
Please add this fix to the source.