Access MenuItemImage through Ref * pSender?

Hello. This is my first time using cocos2d-x (Ver. 3.8.1) and I’m new to C++, so please forgive me for anything I’ve missed.

What I need to do is exchange the position of two buttons placed on my scene. I have the following function wich is called by a button when clicked. I also have the variables MenuItemImage * selected and bool selected_exists.

void Game::Switch(Ref * pSender)
{

if (selected_exists == true)
{
Point aux = selected->getPosition();
selected->setPosition(((MenuItemImage*)(pSender))->getPosition());
((MenuItemImage*)(pSender))->setPosition(aux);

  selected_exists = false;

}

else
{
MenuItemImage * selected = (MenuItemImage*)(pSender);
selected_exists=true;
}
}

What I intended to do was save the first button clicked and then exchange the position with the next clicked button. I’m not even sure if it’s possible to know wich button called the function through Ref * pSender, and I haven’t been able to find any answers online. If my approach is inviable, what kind of solution should I look for? Thank you for your time!

Are you trying to present a toggle switch like iPhone’s setting ON/OFF?
If so you can look into using MenuItemToggle or ui::Checkbox.

If you go with your setup using two MenuItemImage nodes in the manner you’ve setup you could assign tags to each MenuItemImage* or names and then use the respective getNodeByTag[Name].

You may want to test that pSender isn’t equal to selected, though I suppose there’s no harm in setting its position to its own position since it’s not performance critical code.

Also, if you aren’t already you need to declare MenuItemImage * selected in the Game class’ header file instead of where you have it in the code you posted because the way you have it declared it will go out of scope at the } and will be destructed. Where you use selected->[g|s]etPosition that variable doesn’t exist.

Not entirely sure what visual result you desire.

I’m sorry, I should have given more information.
The declarations of selected, selected_exists and Switch(Ref* pSender) on Game.h are as follows:

void Switch(Ref * pSender);
bool selected_exists=false;
cocos2d::MenuItemImage * selected;

The thing is, I don’t want to make a toggle switch. What I need to do is know what buttons of a total of 48 have been pressed and exchange their positions. When one of them is pressed, I need to save it on selected, but it seems the line

	MenuItemImage * seleccionado = (MenuItemImage*)(pSender);

doesn’t work at all, because the value of selected is always NULL. I know the function is being called, because selected_exist does change from false to true. The code inside the if(selected_exists) -corresponding to the second time a button is pressed- causes an access violation, though, being that selected is still NULL.

Is the line above mentioned invalid? Is there a way to know what button called the function through pSender?

Thank you for your time, I really appreciate your help.

You can try to update your code like this. The bool is unnecessary since you can check for nullptr instead. There may also be better ways to handle this by using tags or an array of MenuItems. Hope this helps a little to get you further.

Note: if you’re holding onto a pointer to a node then you do have to make sure that node exists at the time the Switch method is called.

class Game : public ...
{
  //...
  void Switch(Ref * pSender);
  bool selected_exists=false;
  cocos2d::MenuItemImage * selected;
}

void Game::Switch(Ref* pSender)
{
    // pSender should exist at this point, if not probably a release bug
    auto sender = static_cast<MenuItemImage*>(pSender); 
    // it is possible for selected to become invalid
    // if the menu item was removed from the scene or otherwise released.
    if (selected)
    {
        Point tmp = selected->getPosition();
        selected->setPosition(pSender->getPosition());
        pSender->setPosition(tmp);
        selected = nullptr;
    }
    else
    {
        selected = sender;
    }
}
1 Like

Thank you! Looking at my code thanks to your earlier reply I found out that I was unnecessarily declaring selected on the function. It works perfectly now.