Cocos2dxでダイアログ的な何かを作ってみた


# 何を目的に作ったか。
ダイアログ的な表示を簡単に呼べる汎用ライブラリを作成したい。
休みの日についカッとなって作った、今は反省している

# 何処迄作ったか
* ガワを除く、構造を作成
* モーダルレイヤ機能
* タイトル、詳細が空の場合は間を詰める
* ボタンの増減が可能な可変機能

# 実装イメージ
背景はサンプルで実装とは異なります。
Qiitaにアップした動画GIFが不安定なのは何やろ。。
![DialogSample.gif](https://qiita-image-store.s3.amazonaws.com/0/35973/7209f41a-bbb0-ce7e-f412-aa3749300855.gif)


# 呼び出し方
```cpp
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);
```
# 結果の受取
```cpp
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();
}
```

# ライブラリ

```cpp: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();
};
```

```cpp: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);
}
```