2

Cocos2d-x Version 3.17

// Create Button : Type - 1

{
    Sprite *spr1 = Sprite::createWithSpriteFrameName(FRAME_MM_PLAY);
    Sprite *spr2 = Sprite::createWithSpriteFrameName(FRAME_MM_PLAY);

    spr2->setColor( Color3B(200, 200, 200) );

    auto *playButton = MenuItemSprite::create(spr1, spr2, CC_CALLBACK_1(CBirdMainMenu::playBtnPress, this));
    playButton->setScale(1.0f);
    playButton->setEnabled(true);

    auto playMenu = Menu::create(playButton, nullptr);
}

// Create Button : Type - 2

Button *infoButton
    {
        infoButton = Button::create(FRAME_MM_INFO,FRAME_MM_INFO,FRAME_MM_INFO,Widget::TextureResType::PLIST);
        infoButton->setZoomScale(0.2f);
        infoButton->setPressedActionEnabled(true);
        infoButton->addTouchEventListener([&](Ref* sender, cocos2d::ui::Widget::TouchEventType type){
            switch (type)
            {
                case ui::Widget::TouchEventType::BEGAN:
                    break;
                case ui::Widget::TouchEventType::ENDED:
                    this->infoButtonPress();
                    break;
                default:
                    break;
            }
        });

        This->addChild(infoButton, 2);
    }

In Type-2 how to change color of button when clicked. I used single image for all states. I don't like to use separate image. Is it possible to change color of selected sprite in Type2 ? In Type1, for MenuItemSprite , we can easily set color for selected image……In Type-2, if I call setColor on Button, then it is crashing.

infoButton->setColor(Color3B(200, 200, 200)); //Crashed on this

Don't know how to change color of button when pressed.

Guru
  • 21,652
  • 10
  • 63
  • 102
  • i don't see any problem with this. assuming that FRAME_MM_X is a char array of the image names and the image is stored in a texture atlas since you are using `Widget::TextureResType::PLIST`. What is the crash btw? – Yucel_K Oct 21 '18 at 00:10
  • @Yucel_K crash happens only when we call infoButton->setColor...otherwise no crash. – Guru Oct 21 '18 at 16:52
  • have you tried changing the colour right after initializing the Button? in my cocos2dx, everything works fine. im suspecting maybe`infoButton` pointer becomes invalid before `setColor` is called. what is the crash you get? – Yucel_K Oct 21 '18 at 17:08
  • @Yucel_K here is screenshots..thanks for looking. https://app.box.com/s/hefysv8c8nccpcz41piv0z5e6fkceiwc – Guru Oct 21 '18 at 17:40
  • can you show me the where you intializing `toolbar` pointer?I believe i know where its gets released but want to make sure. – Yucel_K Oct 21 '18 at 19:21

1 Answers1

1

you are creating the button and assigning to the InfoButton pointer.

infoButton = Button::create(FRAME_MM_INFO,FRAME_MM_INFO,FRAME_MM_INFO,Widget::TextureResType::PLIST);

the problem is though your infoButton is a local pointer.

Button *infoButton;
  {
    ...
    ...

from the screenshot you have provided, I can see that it's locally created in CBirdMenu::SetupMenu().

you then add the info button as a child to an object pointed by a pointer called toolBar However the moment the CBirdMenu::SetupMenu() ends, your infoButton will no longer be recognised by the lambda expression.

one way and perhaps easiest way is to fix your problem is using dynamic casting on the lambda parameter Ref* sender within the lambda expression.

InfoButton->addTouchEventListener([&](Ref* sender, cocos2d::ui::Widget::TouchEventType type)
{
    cocos2d::ui::Button * infButton = dynamic_cast<cocos2d::ui::Button*>(sender);
    if(infButton)//check if casting done properly
       infButton->setColor(Color3B(0, 200, 0)); //colour set to green.
});

or alternativly, instead of having a local pointer infoButton, store it as a class member of CBirdMenu. this way infoButton will never get lost while the cBirdMenu exists.

here is a quick demo. the header file;

    #include "cocos2d.h"
    #include "ui\CocosGUI.h"
    class HelloWorld : public cocos2d::Layer
    {
    public:
        static cocos2d::Scene* createScene();
        virtual bool init();
        void menuCloseCallback(cocos2d::Ref* pSender);
        CREATE_FUNC(HelloWorld);
    private:
        cocos2d::ui::Button * InfoButton; //member of HelloWorld.
    };

notice the private member cocos2d::ui::Button * InfoButton; And finally the source file where the button is instantiated and assigned to the infoButton pointer.

// on "init" you need to initialize your instance
bool HelloWorld::init()
{
    //////////////////////////////
    // 1. super init first
    if ( !Layer::init() )
        return false;

    Size visibleSize = Director::getInstance()->getVisibleSize();
    Vec2 origin = Director::getInstance()->getVisibleOrigin();

    InfoButton = cocos2d::ui::Button::create("HelloWorld.png", "HelloWorld.png", "HelloWorld.png", ui::Widget::TextureResType::LOCAL);
    InfoButton->setColor(Color3B(255, 0, 0)); //colour is set to red as suppose to.
    InfoButton->setTitleFontSize(InfoButton->getTitleFontSize() * 0.7);
    InfoButton->setPosition(Vec2(visibleSize.width / 2 + origin.x, visibleSize.height / 2 + origin.y));
    InfoButton->addTouchEventListener([&](Ref* sender, cocos2d::ui::Widget::TouchEventType type)
    {
        InfoButton->setColor(Color3B(0, 200, 0)); //colour set to green.
    });
    // add the button as a child to this layer
    this->addChild(InfoButton, 2);
    return true;
}

if you apply the same principle to your code, this should solve your current problem with the lambda. However I'm still not sure what yourtoolBar class does since this is not included in the code. if toolBar is a custom class, i recommend you to move your infoButton from CBirdMenu to toolBar instead if you going with the second approach to adress your issue.

Yucel_K
  • 688
  • 9
  • 17