I need to create a message box with an "OK"-button. When the user touches the button, it should execute a callback. I'm new to this and couldn't find any articles in the docs.
2 Answers
I need too often to show popup message in my games. so I've created a base class and I derived new popup message class from it and override SetupUI() in derived class to show my desired message. in fact you need to put a MenuItem in SetupUI() of new class to implement "ok" button simply.
Note: CreateInvisibleBackgroundButton() works for cocos2dx v2.x and BlockPassingTouch() is its equivalent for cocos2dx v3.x .
Note2: If you want to call different callback for same popup message, you can pass a callback std::function<void(void)> _callbackFunc (cocos2dx v3) as parameter to your dialog and call that when "ok" pressed.
If you need more description just tell me.
PopupNode.h
#ifndef __POPUP_NODE_H__
#define __POPUP_NODE_H__
#include "cocos2d.h"
class PopupNode : public cocos2d::Node
{
public:
CREATE_FUNC(PopupNode);
virtual bool init(); // subclass should have access to call it
void ClosePopup();
private:
void BlockPassingTouch();
void SetupUI();
void CreateInvisibleBackgroundButton(); //THIS FUNCTION IS OUTDATED. KEEP FOR COMPARING COCOS2D 2.X AND 3.X
};
#endif // __POPUP_NODE_H__
PopupNode.cpp
#include "PopupNode.h"
#include "Const/constants_z_order.h"
USING_NS_CC;
bool PopupNode::init()
{
if ( !Node::init() )
{
return false;
}
//////////////////////////////////////////////////////////////////////////
BlockPassingTouch(); //CreateInvisibleBackgroundButton();
SetupUI();
//////////////////////////////////////////////////////////////////////////
return true;
}
void PopupNode::CreateInvisibleBackgroundButton()
{
// Code below works with cocos2dx 2.x
//////////////////////////////////////////////////////////////////////////
///////// THIS FUNCTION IS OUTDATED. KEEP FOR COMPARING COCOS2D 2.X AND 3.X
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
// Size visibleSize = Director::getInstance()->getVisibleSize();
// Vec2 origin = Director::getInstance()->getVisibleOrigin();
// //////////////////////////////////////////////////////////////////////////
// auto lock_menu = Menu::create();
// //lock_menu->setTouchPriority(-1000); // get touch first
// lock_menu->setPosition(origin);
// this->addChild(lock_menu);
// //////////////////////////////////////////////////////////////////////////
// auto invisibleClose = MenuItemSprite::create(NULL, NULL, nullptr);
// invisibleClose->setAnchorPoint(Vec2::ANCHOR_BOTTOM_LEFT);
// invisibleClose->setContentSize( visibleSize );
// invisibleClose->setPosition(origin);
// lock_menu->addChild(invisibleClose );
}
void PopupNode::SetupUI()
{
Size visibleSize = Director::getInstance()->getVisibleSize();
Vec2 origin = Director::getInstance()->getVisibleOrigin();
//////////////////////////////////////////////////////////////////////////
auto cover = Sprite::create("Scene/PopUp/LoadingBackground.png");
cover->setPosition(Vec2(visibleSize.width/2 + origin.x, visibleSize.height/2 + origin.y));
this->addChild(cover, Z_BACKGROUND);
}
void PopupNode::BlockPassingTouch()
{
auto listener = EventListenerTouchOneByOne::create();
listener->setSwallowTouches(true);
listener->onTouchBegan = [](Touch* touch, Event* event){
if(event->getCurrentTarget()->isVisible() == false )
return false;
return true;
};
_eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this);
}
void PopupNode::ClosePopup()
{
this->removeFromParentAndCleanup(false);
}
You can create a new Layer with an box and an CCMenu with one CCMenuItem. The CCMenuItem will be your OK Button where you will set your callback method.
Something like...
CCSprite *box = [CCSprite spriteWithFile:@"box.png"];
box.position = ccp(screen.width/2,screen.height/2);
[self addChild:box];
CCMenuItemImage *okButton = [CCMenuItemImage itemFromNormalImage:@"yes.png" selectedImage:@"ok_button.png" target:self selector:@selector(okMethod)];
CCMenu *menu = [CCMenu menuWithItems:okButton,nil];
menu.position = ccp(box.boundingBox.size.width/2,box.boundingBox.size.height/2);
[box addChild:menu];
Hope it helps, :)
-
\$\begingroup\$ Notice that if there be a
MenuItem(Button) back of your "box.png", touches will pass over this box ! you can handle this by putting a huge button which do nothing behind of your box. \$\endgroup\$Emadpres– Emadpres2014-11-01 20:34:09 +00:00Commented Nov 1, 2014 at 20:34