Fix for CCControlButton crash when trying to clear a background sprite for state or when using one sprite for two states

Fix for CCControlButton crash when trying to clear a background sprite for state or when using one sprite for two states
0.0 0


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);
    nAsBtn->setBackgroundSpriteForState(hSprt, CCControlStateNormal);
    nAsBtn->setBackgroundSpriteForState(nSprt, CCControlStateHighlighted);

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:


void CCControlButton::setBackgroundSpriteForState(CCScale9Sprite* sprite, CCControlState state)
    CCSize oldPreferredSize = m_preferredSize;

    CCScale9Sprite* previousBackgroundSprite = (CCScale9Sprite*)m_backgroundSpriteDispatchTable->objectForKey(state);
    if (previousBackgroundSprite)

        // 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->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));


    // If the current state if equal to the given state we update the layout
    if (getState() == state)

Please add this fix to the source.