Cinder標準のInterfaceGlでそこそこイケてるUIをつくる

[Cinder][cinder]については『[Cinderがすごい話 - Qiita][qiita-numa-cinder]』がいい感じにまとまっているのでどうぞ．

---

Cinderには`InterfaceGl`というUIライブラリが付属しています（実体は[AntTweakBar](http://anttweakbar.sourceforge.net/)のラッパー）．
こいつがそこそこいけてるので，Cinder v0.9.0の[samples/ParamsBasic/src/ParamsBasicApp.cpp](https://github.com/cinder/Cinder/blob/v0.9.0/samples/ParamsBasic/src/ParamsBasicApp.cpp)から派手なやつをピックアップして紹介します．

### 前準備
`InterfaceGl`（のRef）をプライベートフィールドで持っておく．`draw()`関数内の適当な場所で`InterfaceGl`も`draw()`しておく．

```cpp
class SampleApp : public App {
public:
  // snip.

private:
  params::InterfaceGlRef mParams;

  // snip.
};
```

```cpp
void SampleApp::setup() {
  mParams = params::InterfaceGl::create( getWindow(), "App parameters", toPixels( ivec2( 200, 300 ) ) );

// snip.
}
```

```cpp
void SampleApp::draw() {
  // snip.

  mParams->draw();
}
```

この後に出てくる`addParam`や`addText`，`addButton`はドコから呼び出しても大丈夫．実際に描画されるのは`InterfaceGl#draw()`を読んだ時なので，無理にアプリの`draw()`でやるひつようもない．

### 数値
~~お前それでどこで使うねんと言いたくなる感じの~~かっこいいマウスぐるぐる操作で値をいじることができる．

![3255b544-05e6-4472-b4a1-682041019db1.gif](https://qiita-image-store.s3.amazonaws.com/0/14845/29c91e2c-035a-0c3f-ce45-afe9bbb71abc.gif)

> ```cpp
> float mObjSize;
>
> // snip.
>
> mParams->addParam("Cube Size", &mObjSize)
>   .min(0.1f)
>   .max(20.5f)
>   .keyIncr("z")
>   .keyDecr("Z")
>   .precision(2)
>   .step(0.02f);
> ```
>
> 注. 適宜コードを整形してます

## 回転
マウスぐるぐるでオブジェクト回転させたり．

![51b21b18-f49d-48b7-80b2-fe70dacb45bf.gif](https://qiita-image-store.s3.amazonaws.com/0/14845/e69e6e19-7995-df7f-68bd-08e1dab1a3c8.gif)

> ```cpp
> quat mObjOrientation;
>
> // snip.
> 
> mParams->addParam("Cube Rotation", &mObjOrientation);
> ```

`quat`はクォータニオン．[GLM](http://glm.g-truc.net/)の実装を利用している．

### 色
RGB/HSVとAlpha値を数値弄るのと同じようにぐりぐりできる．すぐ上に色のプレビュー出てて便利．

![58ae9385-6120-43b9-8133-9dda1087e770.gif](https://qiita-image-store.s3.amazonaws.com/0/14845/bb89efa7-32ce-ae20-a1bd-4076b70f6e9c.gif)

> ```cpp
> ColorA mColor;
>
> // snip.
>
> mParams->addParam("Cube Color", &mColor);
> ```

`ColorA`はそのまま，透明度付きの色情報．いろんなとこでおなじようにつかえるよ．


### 方向
クォータニオンと同じような感じでベクトルもぐりぐりできる．3次元以外のベクトルだとどうなるかは試してないので不明．

![38733983-1045-4c38-9bba-46d523c59a98.gif](https://qiita-image-store.s3.amazonaws.com/0/14845/2c715f3d-aff9-70cd-8443-41dd6a9fdb2f.gif)

> ```cpp
> vec3 mLightDirection;
>
> // snip.
>
> mParams->addParam( "Light Direction", setter, getter );
> ```

### SelectBox（ComboBox，Spinner的な）
`vector<string>`を渡せばセレクトボックス的なアレもシュッと作れる．

![92b3f32d-9678-4439-9196-308ab6a64924.gif](https://qiita-image-store.s3.amazonaws.com/0/14845/f32ed317-93db-68c3-32a7-f6aaae88aa02.gif)

> ```cpp
> vector<string> mEnumNames;
> int mEnumSelection;
>
> // snip.
>
> mParams->addParam( "an enum", mEnumNames, &mEnumSelection )
>   .keyDecr( "[" )
>   .keyIncr( "]" )
>   .updateFn( [this] { console() << "enum updated: " << mEnumNames[mEnumSelection] << endl; } );
> ```

最後に`updateFn()`がチェインされてるけど，これはどの`addParam()`でも共通に使えるやつ．値が更新された時に渡された関数が呼び出される．サンプルの通り，lambdaでもいいしbindしてもいい．


## 所感
### Pros
- ベクトル・クォータニオンぐりぐり系UIが超便利
- メソッドチェインできる系APIも扱いやすい

### Cons
- 複数のウィンドウをキレイに並べる方法がわからなかった
- マルチバイト文字が使えないらしい

最終的に`InterfaceGl`ではなく[Cinder-ImGui][cinder-imgui]を採用した．

## References
- [Cinder][cinder]
- [Cinderがすごい話 - Qiita][qiita-numa-cinder]
- [simongeilfus/Cinder-ImGui][cinder-imgui]

[cinder]: https://libcinder.org/
[github]: https://github.com/cinder/Cinder
[qiita-numa-cinder]: http://qiita.com/Hiroki11x/items/0952b82c99a60add8444
[cinder-imgui]: https://github.com/simongeilfus/Cinder-ImGui