何を目的に作ったか。
ダイアログ的な表示を簡単に呼べる汎用ライブラリを作成したい。
休みの日についカッとなって作った、今は反省している
何処迄作ったか
- ガワを除く、構造を作成
- モーダルレイヤ機能
- タイトル、詳細が空の場合は間を詰める
- ボタンの増減が可能な可変機能
実装イメージ
背景はサンプルで実装とは異なります。
Qiitaにアップした動画GIFが不安定なのは何やろ。。
呼び出し方
cocos2d::ccMenuCallback action = CC_CALLBACK_1(GameScene::menuStartCallback,this);
std::vector<UIDialogButton*> buttons = {
new UIDialogButton("ルームを作成する",action,1),
new UIDialogButton("ルームを探す",action,2),
};
auto* dialog = UIDialog::create("ダイアログタイトル","このゲームは適当に選択したらはじまります\n※たぶん※", buttons);
addChild(dialog,Z_Dialog,T_Dialog);
結果の受取
void GameScene::menuStartCallback(Ref* Sender)
{
MenuItem* menuItem = (MenuItem*)Sender;
log("%d",menuItem->getTag());
switch(menuItem->getTag()){
case 1:
break;
case 2:
break;
}
dialogClose();
}
void GameScene::dialogClose()
{
UIDialog* dialog = static_cast<UIDialog*>(getChildByTag(T_Dialog));
dialog->close();
}
ライブラリ
UIDialog.h
#include "cocos2d.h"
USING_NS_CC;
struct UIDialogButton {
private:
std::string _name;
cocos2d::ccMenuCallback &_action;
int _tag;
public:
UIDialogButton(std::string name, cocos2d::ccMenuCallback &action,int tag=1)
: _name(name), _action(action), _tag(tag) {}
std::string name() const { return _name; }
cocos2d::ccMenuCallback action() const { return _action; }
int tag() const { return _tag; }
};
class UIDialog : public Layer
{
protected:
Layer* _uiLayer;
public:
static UIDialog* create(std::string title,
std::string content,
std::vector<UIDialogButton*> buttons);
virtual bool init();
virtual void view(std::string title,
std::string content,
std::vector<UIDialogButton*> buttons);
void close();
};
UIDialog.cpp
#include "UIDialog.h"
USING_NS_CC;
UIDialog* UIDialog::create(std::string title,
std::string content,
std::vector<UIDialogButton*> buttons)
{
auto dialog = new UIDialog();
dialog->init();
dialog->view(title,content,buttons);
dialog->autorelease();
return dialog;
}
#define kModalLayerPriority -1
bool UIDialog::init()
{
if (!Layer::init())
return false;
_uiLayer = Layer::create();
addChild(_uiLayer);
return true;
}
void UIDialog::view(std::string title,
std::string content,
std::vector<UIDialogButton*> buttons){
Size winSize = Director::getInstance()->getWinSize();
// 背景作成
auto s = Sprite::create();
s->setTextureRect(Rect(0,0,winSize.width*2,winSize.height*2));
s->setColor(Color3B::BLACK);
s->setOpacity(128); // 透明度
_uiLayer->addChild(s);
// モーダルレイヤ化
auto listener = EventListenerTouchOneByOne::create();
listener->setSwallowTouches(true);
listener->onTouchBegan = [](Touch *touch,Event*event)->bool{
return true;
};
this->getEventDispatcher()->addEventListenerWithSceneGraphPriority(listener, this);
this->getEventDispatcher()->setPriority(listener, kModalLayerPriority);
int size = buttons.size() - 1;
if (title != "") size++;
if (content != "") size++;
float mergin = 150.0f;
float height = mergin * size / 2;
Vector<MenuItem*> item;
if (title != ""){
auto* titleLabel = Label::createWithSystemFont(title, "Arial", 28,Size::ZERO,TextHAlignment::CENTER,TextVAlignment::CENTER);
titleLabel->setPosition(Point(winSize.width/2,winSize.height/2+height));
_uiLayer->addChild(titleLabel);
height -= mergin;
}
if (content != ""){
auto* contentLabel = Label::createWithSystemFont(content, "Arial", 28,Size::ZERO,TextHAlignment::CENTER,TextVAlignment::CENTER);
contentLabel->setPosition(Point(winSize.width/2,winSize.height/2+height));
_uiLayer->addChild(contentLabel);
height -= mergin;
}
int tag = 1;
for (auto b : buttons){
auto* labelBtnLabel = Label::createWithSystemFont(b->name(), "Arial", 48);
auto* itemLabel = MenuItemLabel::create(labelBtnLabel, b->action());
// ボタンのサイズ
//log("%f %f",itemLabel->getPosition().x, itemLabel->getPosition().y);
itemLabel->setPosition(Vec2(0.0f, height));
if (b->tag() != 1) tag = b->tag(); // 指定があれば指定タグ
itemLabel->setTag(tag);
item.pushBack(itemLabel);
height -= mergin;
tag++; // 普段は加算
}
//メニューを作成
auto* menu = Menu::createWithArray(item);
_uiLayer->addChild(menu);
}
void UIDialog::close()
{
Action* action = RemoveSelf::create();
runAction(action);
}