ビルトインのGUI機能、cinder::params
cinder付属のsample ParamsBasicを見ると、cinder::paramsでGUIを作っている。
同僚の李くんいわく、anttweakbarのラッパーらしい。
スライダーを作っただけなのに、キーボード入力、+/-ボタン、なぞのグルグルUIがついてくるのは、なかなか素晴らしい。なぞのグルグルUIとか、役立つのかわからんけど。
個人的にcinder::paramsがいいなぁと思ったのは、GUIの操作をしたときのコールバックをupdateFnに登録できるところ。
ここにラムダ式をセットしたりすると、おしゃれなコードを書いてる気分になっていい。
最近実用した例としては、OpenCVの関数で入力パラメータが奇数であることが条件だったので、その場合に
int sliderValue;
int oddNumberParameter;
params->addParam("window size", &sliderValue).updateFn([this](){ oddNumberParameter = 2*sliderValue+1;});
こんなかんじで書いてみた。
だが、こいつには一個だけ不満があって、xmlにsave/loadする機能がない。。
自前で書けばいいじゃんというツッコミもあるけど、1回別のBlockを探してみることにしました。
Pretzel GUI
再び同僚の李くんに相談したところ、Pretzel GUIというのがまあまあいいよ、とのこと。
PretzelGUI
こちらにはばっちりとxmlへのsave/loadメソッドがついている。
残念ながら、cinder::paramsのupdateFnみたいな機能はないみたいだ。
あと、windowをリサイズしたときとか、GUIパネルをドラッグして移動したあとに、スライダーとマウスの当たり判定にバグが出たことがあった(スライダーのちょっと上にマウスを乗せたときに、反応する)
だが、それ以外は満足。
コード全文
#include "cinder/app/AppNative.h"
#include "cinder/gl/gl.h"
#include "cinder/params/Params.h"
#include "pretzel/PretzelGui.h"
using namespace ci;
using namespace ci::app;
using namespace std;
class GuiExampleApp : public AppNative {
public:
void setup();
void draw();
cinder::params::InterfaceGlRef params;
Pretzel::PretzelGui* pretzel;
int a;
};
void GuiExampleApp::setup()
{
params = cinder::params::InterfaceGl::create(getWindow(), "cinder::params", Vec2i(320, 240));
params->addParam("Slider", &a).updateFn([this]() { console() << "コールバック関数" << std::endl; });
pretzel = new Pretzel::PretzelGui("Pretzel GUI");
pretzel->setPos(Vec2i(320, 0));
pretzel->addSlider("Slider", &a, 0, 100);
pretzel->addSaveLoad();
pretzel->loadSettings();
}
void GuiExampleApp::draw()
{
// clear out the window with black
gl::clear( Color( 0, 0, 0 ) );
params->draw();
pretzel->draw();
}
余談その1 Macで、プロジェクトにあとからPretzel GUIを加えるときに注意
本筋とは関係ないが、XcodeであとからPretzel GUIを追加すると、PretzelGlobal.cppでコンパイルエラーがでる。
エラーメッセージ&該当箇所をみるとすぐわかるが、NSCursorまわりで、Objective-Cのコードが書いてある。
なので、PretzelGlobal.cppをObjective-C++のコードとしてコンパイルするように設定してやればよい。
Xcodeで右側のペインを出して、Typeを指定。
tinderboxで新規にプロジェクトを作るときに、Pretzelを追加している場合は、気にしなくてOK。
どうゆう仕組みになってるのかなぁと思ったら、Pretzelのcinderblock.xmlに以下の記述があった。
<platform os="macosx">
<source compileAs="mm">src/pretzel/PretzelGlobal.cpp</source>
</platform>
compileAsっていうAttributeがあって、指定できるようになっているんですね。
やはり、しっかり設計されているなーという印象のCinder。
余談その2 oF/CinderのGUI
話が長くなりそうなのでここは雑に書きます。
GUIのoFのアドオン/CinderのBlockって結構たくさんあるが、それぞれ設計が違って、おもしろい(もしくは、めんどい)。
- ofxSimpleGuiToo, PretzelGui, cinder::params はclass Tの参照またはポインタをGUIの部品にセットして、GUIを動かすと直接値も変化する系
- ofxUIはコールバックをセットして、GUIに変化があったときの処理を書いていく系
- oFの0.8以降で入ったofxGuiはofxSlider_がTの値へ直接代入できるように、代入演算子がオーバーロードされているという、また違った作り
個人的には、cinder::paramsの、値は直接変わるし、簡単にコールバックも設定できる、という作りが一番好きです。