プログラミング

GIO Ref. translation progress (FINAL TAKE).

翻訳が完了した。これで GLib 系リファレンス・マニュアルのが完了した。
後半は間が空いたけど、まったくの新規の翻訳でもあるので、こんなものか。GIO の翻訳を開始してから7ヶ月ほど、GLib 系リファレンス・マニュアルとしては1年と3ヶ月といったところ。とは言っても、その間に安定版バージョン 2.22 になってしまっているけど:|
安定版としては古いが、ひとまずこのバージョン系列を踏襲して、これ以降も GTK+ その他のリファレンス・マニュアルを翻訳していく予定。
前回同様に、gtk-doc の最新版を使ってコンパイルしているのだけれども、このツールのメンテナのブログによると、highlight (または gnu-highlight) がインストールされていれば、ドキュメントの中にある <programlisting> な引用でプログラミング言語の文法が強調表示されるようになっているとのこと。実際に試してみるとこんな感じ:

gtk-doc-syntax-highligt-20100116.png

ということで完成したドキュメントは次のとおり:
See Also GIO リファレンスマニュアル: v2.18.4 版の API リファレンス
See Also SVN リポジトリ: 翻訳作業の SVN リポジトリ
See Also GIO Reference Manual: オリジナルのドキュメント
See Also バグ報告と追跡: 翻訳バグなどの報告はこちらへどうぞ
See Also GLib リファレンス・マニュアル: GLib ライブラリ同系のドキュメント
See Also GObject リファレンス・マニュアル: GLib ライブラリ同系のドキュメント

Clutter: a beginner’s tutorial in Japanese (TAKE 2).

前回の続き。これで完結。
See Also Clutter: a beginner’s tutorial: 原文
プログラムの一部が間違っていたので修正しておいた :(


大きさの変更やオブジェクトの選択
ここまでで、Clutter を使ってオブジェクトを回転させるのは簡単であることが分かりました – それではもう少し先に進んで、四角形の大きさも変えてみることにします。
ただ Clutter はとても賢いシステムなのに、単純な数値計算なんかはプログラマに実装させてきました。正直に言えば、この点は本チュートリアルで少々思慮に欠けていました。その点を補うため、前言を撤回して、どんな場合でもちゃんと結果の出せる実装を記述したC言語のちいさなヘッダを導入することにします。このファイルをダウンロードし mathhacks.h という名前で作業フォルダに保存して下さい。そして、今まで記述してきたプログラム・ファイルの中から #include ディレクティブでインクルードするよう追加してみて下さい。
そのヘッダ・ファイルを使えば、2つの値の間を補間する数値計算処理を利用できるようになります。これは、四角形を「滑らかに」大きくしたり小さくすることが、0〜1にある値 (倍率) を渡すだけで簡単に実現できると言うことです。補間した値は何か変数に格納しておく必要があるので、次に示すコードを “gdouble rotation” がある行の下に挿入して下さい:

gdouble scale = 0;

その変数を使い、on_timeline_new_frame() 関数に四角形の大きさを変更するコードを追加します – 次のコードを四角形を回転させるコードの後に挿入して下さい:

scale += 0.01;
if (scale > 1.0) scale = 0;
float scale_amount = smooth_step2(1.0, 2.0, scale);
clutter_actor_set_scale(rect1, scale_amount, scale_amount); clutter_actor_set_scale(rect2, scale_amount, scale_amount); clutter_actor_set_scale(rect3, scale_amount, scale_amount); clutter_actor_set_scale(rect4, scale_amount, scale_amount); clutter_actor_set_scale(rect5, scale_amount, scale_amount); clutter_actor_set_scale(rect6, scale_amount, scale_amount);

smooth_step2() は、今回 mathhacks.h の中で定義した小さな即席の関数の1つで、XとYの間をZの値に応じて補間してくれます (Zは0〜1の値です)。このサンプル・プログラムの場合、倍率を表す “scale” にあわせて1.0と2.0との間で補間した値を返します。
この smooth_step2() 関数は、倍率を表す “scale” が0.5未満であれば1.0から2.0の間を補間し、”sclae” が0.5以上ならば2.0から1.0の間を補間します。要するに、四角形の大きさが元のサイズの2倍になったら、今度は倍率を小さくしていくと言うことです。それにより大きくなったり小さくなったりのアニメーションが滑らかに表現できます。同様に、関数名に “2” がついていない版の smooth_step() も用意されており、こちらは四角形を大きくするだけです (訳注: 大きくなった後は四角形を最初から描画します)。
ここまでのサンプル・プログラムをコンパイルして実行すると、四角形が回転しながら大きくなったり小さくなったりするアニメーションをみることができます。どうです? 簡単でしょう – では、どんどん先に進んでみることにしましょう。次はオブジェクトの選択 (Picking) です。
アニメーションの中にはたくさんのオブジェクトが表示されていますが、その中にある1つのオブジェクトをクリックされたことをどのように検出すればよいのでしょうか? 四角形の大きさが変化せず回転もしていないのであれば「クリックした点が四角形の境界線より内側かどうか?」で判定する方法が簡単そうですが、このサンプル・プログラムの場合、オブジェクトを変化させる効果によりそれをとても難しくしています。幸いにも Moblin ではそれをたやすく実現できるようになっています: 画面をクリックしたら、Moblin に任意の関数を呼び出して実行するよう要求できるようになっており、その関数の中でどのアクターがクリックされたのかが分かるようになっています – それでは、まず次のコードを main() の中で最後に create_rect() 関数を呼び出している行の後にそのまま挿入して下さい:

g_signal_connect(stage, "button-press-event", G_CALLBACK(on_stage_button_press), NULL);

ここで “button-press-event” というシグナルに on_stage_button_press() という新しい関数を関連づけます。タイムフレームを実現した時と同様に、この関数は特別な引数を受け取れるようになっているので、必要に応じてコピー&ペーストを行います。新しい関数で処理することは

  1. クリックした点の座標 (X,Y) を Clutter に問い合わせる
  2. この座標を使ってどのアクターがクリックされたかを判定する
  3. 当該アクターを隠す

実際のコードは次のようになります – この関数は main() 関数の前で記述すること:

void on_stage_button_press(ClutterStage *stage, ClutterEvent *event, gpointer data) {
// 画面のどこをクリックしたかを検査する
gfloat x = 0;
gfloat y = 0;
clutter_event_get_coords(event, &x, &y);
// どのアクターがクリックしたのか調査する ClutterActor* clicked = clutter_stage_get_actor_at_pos(CLUTTER_STAGE(stage), CLUTTER_PICK_ALL, x, y);
// クリックしたオブジェクトがステージの場合は無視する if (clicked == CLUTTER_ACTOR(stage)) return;
// クリックした四角形を表示しないようにする clutter_actor_hide(clicked); }

ここまで実装してきたサンプル・プログラムをコンパイルして実行すると、前回のサンプルと同じように四角形が回転しながら大きくなったり小さくなりますが、その中の四角形をクリックして消してしまうことができます。Clutter の Depth-Sort アルゴリズムでは、四角形をステージに追加した順番に並び替えるようになっているため、ある四角形と他の四角形とが交差して重なっている部分をクリックすると、一番上にある四角形がクリックされたと認識されます。

tut_clutter4.png

(Clutter を使えば、オブジェクトを回転させながら大きさを変えることができるということが分かりました。まさに「OpenGL 万歳!」といったところでしょう。)
スコアを記録する
タイムラインを使えば自由にオブジェクトのアニメーションを実現できますが、荒削りの感も否めません – アニメーションに関連する全ての処理を1つの関数にまとめてしまっているので、複雑なアニメーションを実現するには少々厄介です。お分かりかと思いますが、Clutter はスコア付きで面倒をみてくれます。並列でも直列でも実行できるタイムラインのコレクションが用意されているので、必要に応じて使い分けできます。この動きを確認するために、まず最初に現在の on_timeline_new_frame() 関数を2つの部分に分割します – 1つ目は四角形を回転する処理で、もう1つは四角形の大きさを変更する処理です。実際には次のような2つの関数を用意することになります:

void on_timeline_rotation_new_frame(ClutterTimeline *timeline, gint frame_num, gpointer data) {
rotation += 0.3;
clutter_actor_set_rotation(rect1, CLUTTER_Z_AXIS, rotation * 5, 0, 0, 0); clutter_actor_set_rotation(rect2, CLUTTER_Z_AXIS, rotation * 4, 0, 0, 0); clutter_actor_set_rotation(rect3, CLUTTER_Z_AXIS, rotation * 3, 0, 0, 0); clutter_actor_set_rotation(rect4, CLUTTER_Z_AXIS, rotation * 2, 0, 0, 0); clutter_actor_set_rotation(rect5, CLUTTER_Z_AXIS, rotation, 0, 0, 0); clutter_actor_set_rotation(rect6, CLUTTER_Z_AXIS, rotation * 0.5, 0, 0, 0); }
void on_timeline_scale_new_frame(ClutterTimeline *timeline, gint frame_num, gpointer data) { scale += 0.01; if (scale > 1.0) scale = 0; float scale_amount = smooth_step2(1.0, 2.0, scale);
clutter_actor_set_scale(rect1, scale_amount, scale_amount); clutter_actor_set_scale(rect2, scale_amount, scale_amount); clutter_actor_set_scale(rect3, scale_amount, scale_amount); clutter_actor_set_scale(rect4, scale_amount, scale_amount); clutter_actor_set_scale(rect5, scale_amount, scale_amount); clutter_actor_set_scale(rect6, scale_amount, scale_amount); }

ここでは、まだ新しいコードは追加していません – 既存の関数を2つに分割しただけです。これで、まずスコアを新規に生成し、それを使って以前のアニメーションの動作を再構築し、それから2個のタイムラインをスコアに追加して並列で動作させる準備が整いました。ここでは clutter_timeline_set_loop() 関数は使いません。なぜならタイムラインをループさせたくないからです – スコアにループして貰いたいのです。Clutter では関数名の付け方を見れば、その関数で何を処理したいのかが分かるようになっていますが、clutter_score_set_loop() という関数の場合、タイムラインをそれぞれループさせるのではなく、スコア全体をループさせていることがわかると思います。
タイムラインを使った場合と同様に、スコアも直接破棄する必要があります – すなわち、ステージが破棄されてもスコアは自動的に破棄されません。そのため main() 関数の最後の部分を次のように変更して下さい:

// 新規にスコアを1個生成しループにセットする
ClutterScore *score = clutter_score_new();
clutter_score_set_loop(score, TRUE);
// 新規にタイムラインを1個生成し、その所要時間を1/2秒にする ClutterTimeline *timeline_rotation = clutter_timeline_new(500); g_signal_connect(timeline_rotation, "new-frame", G_CALLBACK(on_timeline_rotation_new_frame), NULL);
// タイムラインをスコアに追加する clutter_score_append(score, NULL, timeline_rotation);
// 別のタイムラインを生成し、これも同じように所要時間を1/2秒にする ClutterTimeline *timeline_scale = clutter_timeline_new(500); g_signal_connect(timeline_scale, "new-frame", G_CALLBACK(on_timeline_scale_new_frame), NULL);
// 同様に、このタイムラインをスコアに追加する clutter_score_append(score, NULL, timeline_scale);
// スコアを開始する clutter_score_start(score);
clutter_actor_show(stage);
clutter_main();
// 使用済みのメモリを解放する g_object_unref(timeline_rotation); g_object_unref(timeline_scale); g_object_unref(score);
return EXIT_SUCCESS;

ここまでのプログラムをコンパイルして実行すると、以前の実行結果から特に変化が無いことが分かるでしょう: 以前と同じように四角形が回転しながら大きくなったり小さくなります。その理由は複数のタイムラインをスコアに追加して、それらを並列に実行するよう Clutter に依頼したからです – on_timeline_rotation_new_frame() 関数が一度だけ呼び出されると、その次に on_timeline_scale_new_frame() も一度だけ呼び出されます。
ここで Clutter にやらせたいことは、on_timeline_scale_new_frame() 関数の処理に切り替わる前に、on_timeline_rotation_new_frame() 関数を 500ms 間実行させたたいということです。そのためには、clutter_score_append() 関数の呼び出しを変更する必要があります – この関数の2番目の引数を NULL にします (これは「親に相当するタイムラインは持たない – 可能な時にそのタイムラインを実行させる」という意味になります)。2つ目の clutter_score_append() 関数の呼び出しを次のように変更してみて下さい:

clutter_score_append(score, timeline_rotation, timeline_scale);

ここまでで、四角形の大きさを変更するタイムラインをスコアに追加し、そのスコアを四角形を回転させるタイムラインの親にしました。すなわち、これで2つあるタイムラインは連続して実行されるようになりました: 最初に四角形を回転させて、次に四角形の大きさを変更します。このコードをコンパイルして実行するとわかりますが、これが実際にやりたかったことなのです – 四角形が少しだけ回転すると、回転を停止してちょっとだけ大きくなります。それから再び停止して回転していきます。この動作を繰り返すわけです。

tut_clutter4_5.png

もっと色の付いた四角形をたくさん描画する
既に説明したように、Clutter ではいろいろな種類のアクターを利用できますが、それらのほとんどを同じ方法で扱うことができます (ここがすごいところなのですが)。 例えば単に四角形を描画するのではなく、写真を回転させたり大きさを変えたいのであれば、create_rect() 関数の中にある1行を変更するだけです – すなわち、色のついた四角形の代わりに用意した画像を使用します。まず、この関数の先頭の行を次の行で置き換えます:

ClutterActor *rect = clutter_texture_new_from_file("media/card_1.png", NULL);

他に変更することはありません。ここでプログラムをコンパイルして実行させると、前のサンプルのように四角形ではなく指定した画像が描画されるはずです。

tut_clutter5.png

(Clutter は PNG だとか JPEG 形式の画像を読み込んで、他の種類のアクター同様に扱うことができます。)
さらに Clutter は、文字列のような、もっと複雑なオブジェクトも扱うことができます – 先ほど変更した行を次の行で置き換えてみて下さい。どうです?簡単でしょう:

ClutterActor *rect = clutter_text_new_full("Sans 24", "Hello, world", &col);

そうです、これだけで今までの四角形が文字列から構成されるメッセージに変わります (回転したり大きさが変わるのは前と同じですが)。clutter_text_new_full() 関数に渡す最初の引数は使用するフォントの名前とサイズです。2番目の引数は実際に表示する文字列で、3番目の引数はその文字列を描画する際の色になります。
但し、ここで描画している文字列はそれほど複雑なものではありませんが – 実際にはキーボードから入力した文字列だとか、改行文字を含む長い文章も同じように扱えます。このようなことを試してみるには2点ほど変更する必要があります。 まず最初に、次の行を create_rect() 関数にある clutter_text_new_full() 関数の下に追加します:

clutter_text_set_editable(CLUTTER_TEXT(rect), TRUE);

次に on_stage_button_press() 関数を変更します。今回は、クリックしたアクターを消すのではなく、ユーザにキーボードのフォーカスを与えて何か文字を入力できるようにします。この関数の最後を次のように変更します:

ClutterActor* clicked = clutter_stage_get_actor_at_pos(CLUTTER_STAGE(stage), CLUTTER_PICK_ALL, x, y);
if (clicked == CLUTTER_ACTOR(stage)) return;
clutter_actor_grab_key_focus(clicked);
tut_clutter6.png

(Clutter では面倒な手続きなしで文字列を扱うことができます。注意点: 画面の vsync を有効にした方がもっと綺麗な結果になるでしょう。)
最後に紹介するテクニック
本チュートリアルを切り上げる前に、試してもらいたいことが3つほどあります。最初に、サンプル・プログラムのウィンドウ・タイトルである “./clutterapp” ですが、この表記をそろそろ捨てさってしまってもよい時期でしょう。次のコードを main() 関数の clutter_actor_new() を呼び出す直前に追加してみて下さい:

clutter_stage_set_title(CLUTTER_STAGE(stage), "Spinny boxes ahoy!");

次に、Clutter が提供している全てのアクターは自分に関連づけることが可能なイベント (シグナル) を持ちます – マウスをクリックした、マウスを移動した、キーを押下した などなど。さらに、これらのイベントは特定のアクションに関連づけることが可能になっています。ここで重要なポイントは、アクターなるオブジェクトを任意のイベントに反応するよう指定するということです。すなわち、アクターは自分が発行することになるイベントを持つよう Clutter に指示するできるということです。Clutter の大部分のオブジェクトはイベントに反応しません。なぜなら、イベントに反応するのは CPU の無駄遣いだからです。そのため、利用したいイベントを有効にて下さい。そうしないとなぜ動作しないのかあれこれ考えることになりますよ!
イベントに反応する四角形を生成する場合、次に示すようなことをします:

ClutterActor *rect = clutter_rectangle_new_with_color(&col);
clutter_actor_set_size(rect, 256, 128);
clutter_actor_set_position(rect, 128, 128);
clutter_actor_set_reactive (rect, TRUE);
g_signal_connect (rect, "button-press-event", G_CALLBACK (on_rect_button_press), NULL);

ご覧のとおり、ここでは on_rect_button_press() という関数をコールバックとして四角形に関連づけています。この関連づけは最初に紹介した on_stage_button_press() 関数の時と全く同じです。但し、今回は (ご想像のとおり) ClutterActor 型のオブジェクトを第1引数として渡して関数の中でアクセスできるようにしています。このサンプル・プログラムでは四角形をクリックするとその色を変更することにします – それでは、次のコールバック関数を追加して下さい:

gboolean on_rect_button_press(ClutterActor *actor, ClutterEvent *event, gpointer data) {
ClutterColor newcol = { rand() % 256, rand() % 256, rand() % 256, 255 };
clutter_rectangle_set_color(CLUTTER_RECTANGLE(actor), &newcol);
return TRUE; }

ステージの上で回転している四角形をクリックすると、Clutter はそのアクターをコールバック関数の第1引数に格納してくれます。いろいろな四角形に同じコールバック関数を関連づけ、その中からクリックした四角形だけを見つけてくれるというわけです。もし、この手法を採用せずに、ステージがクリックされた時にオブジェクトを直接判定するような処理を行うのであれば、CLUTTER_PICK_ALLCLUTTER_PICK_REACTIVE に変更して、四角形だけを検出するように設定してみて下さい。
最後に、本チュートリアルではアニメーションの技法について大部分を割愛してきました。なぜなら、その説明は少々一筋縄にはいかないものであり、初心者向きのチュートリアルとしてはその範疇を超えているからです。とはいえ、Clutter でアニメーションを作成するのが本当に簡単であることについてさえも言及していないのあれば、それはそれで筆者の怠慢と言えますが。そして、clutter_actor_animate() という魔法の関数がやってくれることを一言で表現すると、アニメーションに関する複雑な処理を全てラッピングして隠してくれる上に、面白そうな好奇心を抱かしてくれるもの、と言えます。
このサンプル・プログラムを実行する前に、既存のコードを少し整理しておきましょう – 例えば、タイムラインは複数個ありますが、実際はそんなに必要ありません。整理したプログラムは次のようになります:

#include <clutter/clutter.h>
#include <stdlib.h>
// 6個のアクターとそれを動かすステージ ClutterActor *stage = NULL; ClutterActor *rect1 = NULL; ClutterActor *rect2 = NULL; ClutterActor *rect3 = NULL; ClutterActor *rect4 = NULL; ClutterActor *rect5 = NULL; ClutterActor *rect6 = NULL;
// この関数で色のついた四角形を生成する ClutterActor *create_rect(ClutterColor col) { ClutterActor *rect = clutter_rectangle_new_with_color(&col); clutter_actor_set_size(rect, 256, 128); clutter_actor_set_position(rect, 256, 256); clutter_actor_set_anchor_point(rect, 128, 64); clutter_container_add_actor (CLUTTER_CONTAINER (stage), rect); clutter_actor_show (rect);
return rect; }
// この関数については後で実装する予定... void on_stage_button_press (ClutterStage *stage, ClutterEvent *event, gpointer data) { // ここに処理を書く }
int main(int argc, char *argv[]) { clutter_init (&argc, &argv);
ClutterColor stage_color = { 0, 0, 0, 255 };
stage = clutter_stage_get_default(); clutter_actor_set_size (stage, 512, 512); clutter_stage_set_color (CLUTTER_STAGE(stage), &stage_color);
ClutterColor red = { 255, 0, 0, 128 }; ClutterColor green = { 0, 255, 0, 128 }; ClutterColor blue = { 0, 0, 255, 128 }; ClutterColor yellow = { 255, 255, 0, 128 }; ClutterColor cyan = { 0, 255, 255, 128 }; ClutterColor purple = { 255, 0, 255, 128 };
rect1 = create_rect(red); rect2 = create_rect(green); rect3 = create_rect(blue); rect4 = create_rect(yellow); rect5 = create_rect(cyan); rect6 = create_rect(purple);
g_signal_connect (stage, "button-press-event", G_CALLBACK (on_stage_button_press), NULL); clutter_stage_set_title(CLUTTER_STAGE(stage), "Spinny boxes ahoy!"); clutter_actor_show (stage);
clutter_main ();
return EXIT_SUCCESS; }

このサンプル・プログラムをコンパイルして実行すると、6個の四角形が、まるで命を吹き込んでもらいたいのを待っているかのように、全て真ん中にじっとした状態で表示されるはずです。ここで実際にやりたいことは、clutter_actor_animate() 関数を使い、これらの四角形を回転させながらステージの別の場所へ飛ばすということです。この clutter_actor_animate() 関数には驚くべき機能がいくつか搭載されていますが、その中から3つほど説明します:

  1. アニメーションの種類を簡単に変更できる
  2. 1回だけの呼び出して、いろいろなオブジェクトのアニメーションを作成できる
  3. 前のアニメーションが終了する前に clutter_actor_animate() 関数を呼び出すと、Clutter はそれを「賢くエレガントに」処理してくれる

サンプル・プログラムの “// ここに処理を書く” というところに、次のコードを記述して下さい:

move_rect(rect1);
move_rect(rect2);
move_rect(rect3);
move_rect(rect4);
move_rect(rect5);
move_rect(rect6);

まだ move_rect() なる関数は定義していませんが、生成した四角形を引数にして何回か呼び出すものだと推測することができます。この move_rect() 関数は、1個の四角形をランダムに回転させながらステージの上のランダムな場所に移動します – で、ここで重要なポイントは、乱数として得られたランダムな値を整数値ではなく実数値として指定しなければならないと言うことです。もしここでそのまま整数値を使ってしまうと、ほぼ確実にプログラムはクラッシュします。そのため、float 型にキャストしてあげて下さい (それだけです)。
move_rect() 関数の実装は次のようになります:

void move_rect(ClutterActor *rect) {
clutter_actor_animate (rect,
CLUTTER_LINEAR,
1000,
"x", (float)(rand() % 512),
"y", (float)(rand() % 512),
"rotation-angle-z", (float)(rand() % 360),
NULL);
}

実際には、ランダムにクリックすることで clutter_actor_animate() 関数を別々に複数回呼び出すことになります。それでは詳細を見ていくことにします:

  1. CLUTTER_LINEAR がアニメーションの種類で、アニメーション中は同じスピードでオブジェクトを移動します
  2. 1000 はアニメーションを実行する時間 (単位はミリ秒)です
  3. x” がある行はアクターを移動する先のX座標を計算しており、”x” はアクターのプロパティ名で文字列として指定します
  4. rotation-angle-z” もアクターのプロパティ名で、これでアクターを回転角を計算します
  5. アクターのプロパティを全て指定し終わったら、最後に NULL を渡します

このプログラムをコンパイルして実行し、ステージ上のどこかをクリックすると四角形が動き出します。でも、それだけでは少々退屈ではありませんか? clutter_actor_animate() 関数で指定した CLUTTER_LINEAR を CLUTTER_EASE_IN_OUT_BACK に変更し、もう一度コンパイルして実行してみて下さい。その結果はまだ話していませんが、きっと気に入ると思います…

tut_clutter7.png

(ステージの周りを四角形が優雅に飛んでいきます – これは画像や文字列を使っても簡単に実現できます。あるいは他の種類のアクターでも実現んできるでしょう)
とりあえず…以上です
本チュートリアルで紹介した内容は Clutter の入門書なる部分のみを対象していますが、これを執筆した数時間でいろいろと多岐にわたり充実した内容に仕上がったと思います。ここで、Canonical 社が少なくとも Ubuntu Netbook Remix (UNR) の GUI として Clutter を採用した理由は明白でしょう。Clutter は、賢く魅力的なユーザインタフェースを本当に素早く簡単に作成する手法を提供しています。実際のところ、UNR のユーザ・インタフェースを手にとって、それが本当かどうかを確認しできますし、その際はこう思うかもしれません – 「たぶん、私にも作れるかもしれない」。そう、あなたにもできます。

Clutter: a beginner’s tutorial in Japanese (TAKE 1).

Moblin (日本語サイトなんかあったのかぁ) で採用されている UI のフレームワークである Clutter バージョン 1.0 の初心者向け(?)チュートリアルを日本語にしてみた。このチュートリアルは TuxRadar Linux というフリーソフトウェアに関する技術ニュースやチュートリアルなんかを執筆し公開しているウェブサイトのもの。原文はとても「流暢な英語」(口語体でイギリス英語) なので、どうでもよいところ (ウーとかアーとか唸ったり、つまらないジョークだったり) :P は無視した。原文は全体的に読みづらい印象あり。ちなみに Clutter の本家では 0.9 までの古いバージョンのチュートリアルは公開されているけど、1.0 では API も変更されているので、バージョン 1.0 向けはこのチュートリアルが最初かも。
本文の中で説明しているけど、このチュートリアルはあくまでも一時的なもので、現在は Python を使った本格的なチュートリアルを作成中とのこと。
【更新】
一気に読み上げてブログにまとめてしまおうとしたけど、かなりの長文になってしまい、ブログ形式で記述・修正するにはそれなりに手間がかかるため何回かに分割して掲載することにした。まずはアニメーション作成までにする。


Moblin には「いけてる」機能がたくさんありますが、その中でも Clutter がナンバー1の人気でしょう。なぜかですって?
OpenGL のアクセラレーション付きで、オブジェクト指向で、GTK+ に統合された API があなたを納得させられないのであれば、おそらくあなたが今使っているのは強力なアニメーション・フレームワークだとか、簡単にテクスチャを操作でき「電光石火」でオブジェクトを取得できるほど素晴らしいシステムなんでしょうね (という遠回しの皮肉:訳注)。
但し Clutter にも1つ問題があります。それは参考になるドキュメントがホントに少ないということです。Clutter の使い方を学習したいと考えているハッカーは大勢いますが、今すぐ始めるにしてはウェブにも幾分情報が不足しています。私たち編集者はユーザ志向ではないオープンソース・プロジェクトは嫌いなので、最小限の時間で Clutter を習得するしたいと考えている人達のために、チュートリアル的なガイドを数時間を費やして作成してみました。
インテル社はせっかくの素晴らしい技術を手持ちぶたさにしないよう、我々 TuxRadar に寄付してくれるほど親切な企業です。そのため一時的ではありますが、私たちの記事の横に Moblin に関する広告を載せることにしました (原文にあるフラッシュを使った広告のこと)。定期購読者のみに提供している記事をご覧いただいている Linux Format の読者らはモバイル系 Linux に「捧げた」特集記事をご覧いただける予定です。我々 TuxReadar では次回の記事から Python を使った Moblin 向けのプログラミング・チュートリアルの連載を開始する予定です。
ご存じのとおり、Moblin で面白い技術の1つが Clutter であり、インテルのグラフィックス・ライブラリは Moblin や Ubuntu Netbook Remix のユーザインタフェースのようなフロント・エンド部で広く利用されています。Clutter は理解しやすく、使いやすく、加えてまったく面白い技術です。たとえ、まだ試したことが無いという場合でも、ご安心下さい。私たちが Clutter を使ったプログラミングを身につけるための簡単な方法を紹介します。あるいは、Clutter をもっと理解したいのであれば、先ほどの Moblin の広告をクリックしてみて下さい。そこには、ここで紹介したことの他にもいろいろな情報があります。
覚えておいてほしいこととして、あくまでのこの記事は Clutter のドキュメントで今現在不足している箇所を補うための「臨時措置」みたいなものだということです。私たちは、もっと広い視野でみた Python を中心とする Clutter のチュートリアルを作成中ですが、それを完成するには2,3ヶ月必要であるとみています。その間は、ここで紹介するチュートリアルで我慢していただき、Clutter を使ったプログラミングを楽しんで欲しいと考えています。
初めの一歩
私たちはのらりくらりと紹介していくつもりはありません – 詳細な理論の説明は割愛して早速 Clutter を使ってみることにします。まず最初に、Clutter のアプリケーションをビルドするのに必要なものをインストールして下さい – もし Debian/Ubuntu をお使いなら libclutter-1.0.0 と libclutter-1.0-dev、そして当然ながら GCC も必要です。
Clutter を使って作成したウィンドウを「ステージ」(Stage) と呼び、「アクター」(Actor) と呼ばれるいくつかのオブジェクトをそのステージに追加することができます。アクターをステージに追加すると、そのオブジェクトの描画は Clutter が担当します – ステージの上にあるアクターはあちこち自由に移動させたり回転したり、大きさを変更したりなどの命令を出すことができ、それらの処理は全て Clutter がまかなってくれます。
本当に簡単なオブジェクトを題材に Clutter を使ってみることにしましょう。そうすることで、自分の環境で Clutter の開発ができる準備が整っているかどうかを確認することができるでしょう。ここで紹介したコードをコピーして example.c という名前のついたファイルに貼り付けてみて下さい:

#include <clutter/clutter.h>
#include <stdlib.h>
int main(int argc, char *argv[]) { clutter_init(&argc, &argv);
ClutterColor stage_color = { 0, 0, 0, 255 };
ClutterActor *stage = clutter_stage_get_default(); clutter_actor_set_size(stage, 512, 512); clutter_stage_set_color(CLUTTER_STAGE(stage), &stage_color); clutter_actor_show(stage);
clutter_main();
return EXIT_SUCCESS; }

そしてコマンドラインから以下を実行します:

$ gcc example.c -o clutterapp `pkg-config clutter-1.0 --cflags --libs`

エラーなくコンパイルが終了したら、コマンドラインから “./clutterapp” と入力してサンプル・プログラムを起動できます。ここで、古いバージョンのディストリビューション (例えば Ubuntu 9.04 など) では Clutter のパッケージもバージョン 1.0 ではなくバージョン 0.9 を使用することになると思いますが、このバージョンはバージョン 1.0 と 100% 互換性は無いので注意して下さい。もしディストリビューションのバージョンをアップグレードして Clutter のバージョン 1.0 を利用する予定がないのであれば、古い方の実装に合わせて関数名と、pkg-gconfig の呼び出しを変更する必要があります (例えば Ubuntu 9.04 ならば clutter-0.9)。
一度でもサンプル・プログラムが動いたのを見てしまうと、それ以上はつまらなく見えてしまうかもしれませんが: “./clutterapp” を起動すると、背景が黒くタイトルバーを持つウィンドウが表示されます。そして、えっと、それだけです。特に記憶に残る程のものではありませんが、実はそれが重要なポイントです。なぜなら、この状態は Clutter の内部で設定が全て適用され、Clutter のアプリケーションとして準備が整った状態を表しているからです。

tut_clutter1.png

(初めて作成した Clutter のアプリケーション – ただ単に黒い背景を持つ大きなウィンドウですが、お使いのシステムが Clutter を使って開発できる環境になったことの証明でもあります。)
それでは、このサンプル・プログラムがやっていることを簡単に説明してみることにします…

  • clutter_init() は Clutter を「作動させる」関数なので、Clutter を使ったプログラムを作成する際はこの関数を呼び出すことになります。この関数に argcargv を引き渡していますが、その理由は Clutter にはコマンドラインのオプションがいくつか用意されており、このように引き渡すことでそれらを指定できるようになっています。そのオプションについては後で説明しますが、ここで知っておくべきことは、この関数に Clutter 専用のオプションを引き渡すと、Clutter は、この argcargv の解析を行って、それが完了した引数は自動的にその変数から削除されるようになっており、これ以降の処理ではそれらの「引数」は参照できなくなるということです。
  • ClutterColor は、1個の色を表す情報 (赤、緑、青、アルファ値) を格納するための構造体にすぎません。色の情報は0〜255の範囲内で指定したり、0x00〜0xff の16進数で指定することができます。
  • ClutterActor は Clutter の中で最も重要なデータ型です。このサンプル・プログラムではデフォルトのステージを取得する目的でこの型を使っています。デフォルトのステージとは clutter_init() 関数を呼び出した時に Clutter が私達のために用意してくれるオブジェクトです。専門用語で説明すると、Clutter のステージは Clutter 専用のデータ型なのですが、私たちの目が届かないところで ClutterActor からキャストされた型でしかなく、プログラムの中で必要に応じてキャストし直すことが可能になっています。
  • clutter_actor_set_size() 関数を使って1個のアクターの大きさを指定します。アクター (ここではステージ) を第1引数として渡してから、横と縦の大きさをそれぞれ第2引数と第3引数で指定しています。
  • clutter_stage_set_color() は、お分かりかと思いますが、ステージの色をセットする関数です。
  • clutter_actor_show() はアクターを表示する関数です。この関数は重要で、これなしでは (このサンプル・プログラムにある) ウィンドウやその他のアクターを表示することができません。
  • clutter_main() は Clutter のメイン・イベント・ループを生成する関数です。この関数を呼び出した時点で、制御が Clutter 側に渡ります。そして何か興味のあるイベントが発生したらその制御を私たち (サンプル・プログラム) に戻してくれます。しかしながら、ご覧のとおり、このサンプル・プログラムでは何も発生しません。これは、あなたがウィンドウを閉じるまで Clutter は何もせずブラブラしている状態であることを意味しています。

以上が Clutter の基本的なプログラムになります – このコードをテンプレートとして利用し、いろいろ追加していくことで新しいプログラムを素早く簡単に作成できるはずです。事実、それが実際にやりたいことでしょう: それでは、これ以降でステージにアクターを追加してみることにします。
Clutter はいろいろな種類 (型) のアクターを提供してくれていますが、ここで使う型は ClutterRectangle と呼ばれているものです。ステージを使った場合と同様に、ClutterRectangle 型を ClutterActor 型にキャストすることができるので、そのように実装してみましょう – 次のコードをサンプル・プログラムで clutter_actor_show() 関数を呼び出している行の直前に挿入してみて下さい:

ClutterColor actor_color = { 0, 255, 0, 128 };
ClutterActor *rect = clutter_rectangle_new_with_color(&actor_color);
clutter_actor_set_size(rect, 100, 100);
clutter_actor_set_position(rect, 100, 100);
clutter_container_add_actor(CLUTTER_CONTAINER(stage), rect);
clutter_actor_show(rect);

このコードは、新たに緑色 (透明度は 50%) をした矩形を生成して、その大きさと位置を指定し、ステージに追加しています。CLUTTER_STAGE() というマクロの使い方に注意して下さい – これはステージという1アクターを ClutterStage 型にキャストする際に使用します。
矩形を生成した後は、それをステージに追加して表示してやることで、あとは Clutter が実際に描画してくれます。
コンパイルした “./clutterapp” を実行すると、今までよりもすこしだけ面白みのあるウィンドウが表示されるでしょう: 1個の四角形が表示されるだけですが!はいはい、分かっています。ちょっと飽きてきましたね。大丈夫です – ここからもっと面白いものにしていきます…

tut_clutter2.png

(Clutter のウィンドウの中には ClutterRectangle 型のアクターが1つ含まれているので、漠然ではありますが面白そうになってきました)
必要に応じて四角形を描画する
ちょっとコードを整理して、もっと簡単に矩形を生成したり大きさを指定できるようにしてみます。では、次のコードをサンプル・プログラムに追加してみて下さい:

ClutterActor *create_rect(ClutterColor col) {
ClutterActor *rect = clutter_rectangle_new_with_color(&col);
clutter_actor_set_size(rect, 256, 128);
clutter_actor_set_position(rect, 128, 128);
clutter_container_add_actor(CLUTTER_CONTAINER(stage), rect);
clutter_actor_show(rect);
return rect; }

この関数は指定した色で四角形を生成し、ステージの特定の位置に配置します。この関数を呼び出す前に “stage” の定義を移動し、プログラム内のどこからでも参照できるようにしておく必要があります。さらに四角形を表すリファレンスもグローバルで宣言しておいて下さい。すなわち、次の2行を #include 文の直後に挿入することになります:

ClutterActor *stage;
ClutterActor *rect1 = NULL;

重要 (という程でもないと思うが…:訳注) ここでは、ヘッダ・ファイルを用意して前もって全ての関数を定義するようなことはしていません。そのため、自分の関数は正しい順番でプログラムのファイルに配置していくようにする必要があります – もし関数Aが関数Bを呼び出す場合、関数Bはファイルの中で関数Aよりも前に記述しておく必要があります。上の create_rect() 関数は main() 関数から呼び出すことになるので、main() よりも前に配置しておいて下さい。これ以降でも、いろいろな関数を定義する予定なので、それらを呼び出す前に、予めプログラムのファイルに挿入しておく必要があるので注意して下さい。
ということで、main() 関数を次にように変更します:

int main(int argc, char *argv[]) {
clutter_init(&argc, &argv);
ClutterColor stage_color = { 0, 0, 0, 255 };
// ローカルではなく、グローバル変数の stage を使う stage = clutter_stage_get_default(); clutter_actor_set_size(stage, 512, 512); clutter_stage_set_color(CLUTTER_STAGE(stage), &stage_color);
// 新しく追加した関数を呼び出して四角形を生成する ClutterColor red = { 255, 0, 0, 128 }; rect1 = create_rect(red);
clutter_actor_show(stage);
clutter_main();
return EXIT_SUCCESS; }

ここは、それほど大きな変更ではありませんでした。実際のところ、プログラムをコンパイルして実行してみると前と似たような結果になるのが分かるでしょう。但し、これからは必要に応じて矩形を生成できるようになったので、いろいろな色でいろいろな形の四角形を生成し、それらをアニメーションのように動かしてみます。「アニメーション?」 ええ、そうです。まだそれについては説明していませんが、心配は無用です。とっても簡単です。
Clutter でアニメーションを実現する際は「タイムライン」(Timeline) を使います。そして “ticks” という時間単位で通知される度に、コマ撮りのように画像を更新してアニメーションにします。
それではプログラムを変更して複数の四角形を描画してみましょう。まだアニメーションを実行するためのコードは挿入しません。まず複数個の四角形が正しく描画されることを確認しましょう。プログラムの先頭にある変数の定義を次のように変更して下さい:

#include <clutter/clutter.h>
#include <stdlib.h>
ClutterActor *stage; ClutterActor *rect1 = NULL; ClutterActor *rect2 = NULL; ClutterActor *rect3 = NULL; ClutterActor *rect4 = NULL; ClutterActor *rect5 = NULL; ClutterActor *rect6 = NULL;

それでは、今まで同様に stage 変数を定義し、かつ6つの四角形を表すリファレンスを用意します。これら6つの四角形は create_rect() 関数を使ってそれぞれ別々の色で生成するため、main() 関数を次のように変更します:

int main(int argc, char *argv[]) {
clutter_init(&argc, &argv);
ClutterColor stage_color = { 0, 0, 0, 255 };
stage = clutter_stage_get_default(); clutter_actor_set_size(stage, 512, 512); clutter_stage_set_color(CLUTTER_STAGE(stage), &stage_color);
ClutterColor red = { 255, 0, 0, 128 }; ClutterColor green = { 0, 255, 0, 128 }; ClutterColor blue = { 0, 0, 255, 128 }; ClutterColor yellow = { 255, 255, 0, 128 }; ClutterColor cyan = { 0, 255, 255, 128 }; ClutterColor purple = { 255, 0, 255, 128 };
rect1 = create_rect(red); rect2 = create_rect(green); rect3 = create_rect(blue); rect4 = create_rect(yellow); rect5 = create_rect(cyan); rect6 = create_rect(purple); clutter_actor_show(stage);
clutter_main();
return EXIT_SUCCESS; }

次に、このサンプル・プログラムをコンパイルしても6個の四角形は表示されません – 四角形は1個だけしか表示されないのです。これは、なぜなら全ての四角形が同じ場所にあるからです。全てが重ね合わさってしまったというわけです。
ここで面白いことに挑戦してみます: これらの四角形を回転させてみましょう。まず、回転する際の情報を保存するための変数を用意します。次のコードを変数を定義している場所に追加してみて下さい:

gdouble rotation = 0;

それから、タイムラインを生成して有効にします。タイムラインを生成するには clatter_timeline_new() 関数を使い、タイムラインの更新間隔を Clutter に伝えます。この値の単位はミリ秒なので、”1000″ は1秒を表します。タイムラインを生成したら、アニメーションとして画像を更新する際に呼び出す関数に “new-frame” というシグナルを関連づける必要があります。最後にタイムラインをループさせるよう指示し、実際にタイムラインを動かします。
では main() 関数の中で6番目の四角形を生成する create_rect() 関数を呼び出した後に、次のコードを挿入して下さい:

ClutterTimeline *timeline = clutter_timeline_new(60);
g_signal_connect(timeline, "new-frame", G_CALLBACK(on_timeline_new_frame), NULL);
clutter_timeline_set_loop(timeline, TRUE);
clutter_timeline_start(timeline);

on_timeline_new_frame() 関数は、実行の制御が Clutter から戻ってきた時に呼び出されるようになっているので、画像を更新してアニメーションが動いているようにみせることができるのです。この関数は専用の引数を受け取ることになっていますが、ここでは問題ありません – ここで変数を外しても後でコピー&ペーストできますから。
この on_timeline_new_frame() 関数が処理する内容は単純です: “rotation” という変数の値を少しだけ増やし、clutter_actor_set_rotation() 関数を使って四角形の回転角をそれぞれ異なる量だけ変更します。四角形はグローバル変数として全て保持しているので大して難しいことはありません。それでは on_timeline_new_frame() 関数をプログラムに追加してみて下さい:

void on_timeline_new_frame(ClutterTimeline *timeline, gint frame_num, gpointer data) {
rotation += 0.3;
clutter_actor_set_rotation(rect1, CLUTTER_Z_AXIS, rotation * 5, 0, 0, 0); clutter_actor_set_rotation(rect2, CLUTTER_Z_AXIS, rotation * 4, 0, 0, 0); clutter_actor_set_rotation(rect3, CLUTTER_Z_AXIS, rotation * 3, 0, 0, 0); clutter_actor_set_rotation(rect4, CLUTTER_Z_AXIS, rotation * 2, 0, 0, 0); clutter_actor_set_rotation(rect5, CLUTTER_Z_AXIS, rotation, 0, 0, 0); clutter_actor_set_rotation(rect6, CLUTTER_Z_AXIS, rotation * 0.5, 0, 0, 0); }

この時点でプログラムをコンパイルし実行することができます。6つの四角形がその左上を中心に角度を計算しながらそれぞれ回転していくのが分かるでしょう。この先に進む前に、ちょっとだけプログラムを変更することにします。

  1. Clutter は、そのオブジェクトに属しているメモリを自動的に解放してくれるという賢い作りになっていますが、これは通常、ステージに取り付けられているオブジェクトのみが対象です。今回生成したタイムラインはステージには取り付けていないので、そのメモリは使い終わったら手動で解放しなければなりません。そのために、main() 関数の中にある clutter_main() を呼び出した後すぐに次のコードを追加して下さい:
    g_object_unref(timeline);
    
  2. 四角形がその左上隅を中心として回転することは予想外でした。代わりにアクターの中心を基点に回転させればもっと綺麗でしょう。これは、Clutter で「アンカー・ポイント」(Anchor Point) と呼ばれている情報を変更することで実現できます – すなわち、四角形はアンカー・ポイントを中心に回転することになります。create_rect() 関数に次のコードを追加してみて下さい:
    clutter_actor_set_anchor_point(rect, 128, 64);
    
tut_clutter3.png

(透明な四角形が回転しているのがわかりますか? そうだとしたら成功です)
(TAKE2へ続く)

GIO Ref. translation progress (TAKE 3).

最後に翻訳してからずいぶんと間が空いてしまった GIO のリファレンス・マニュアルだけど、なんとか折り返し地点に到達した (ような気がする。但し、GIOの折り返し地点であってまだまだ先は長いけれども…:|)。
ちなみに、今回からこの間リリースされた gtkdoc バージョン0.13 を使ってドキュメントをコンパイルしている。このバージョンは Bugfix が主だけれど、CSS も更新されていてサンプルコードには行番号が付与されるなど前バージョンとはちょっと違った趣あり。あと、他のドキュメントのリンクを埋め込む gtkdoc-fixxref コマンドの必須オプションが追加されたため、–enable-gtkdoc しているパッケージは修正が必要
See Also GIO リファレンスマニュアル: v2.18.4 版の API リファレンス
See Also SVN リポジトリ: 翻訳作業の SVN リポジトリ
See Also GIO Reference Manual: オリジナルのドキュメント
See Also バグ報告と追跡: 翻訳バグなどの報告はこちらへどうぞ
See Also 前バージョンのドキュメント: その他関連するドキュメント一覧

GIO Ref. translation progress (TAKE 2).

第二章の API リファレンスは1節の File Operations から3節の Asynchronous I/O まで翻訳完了。
しかし誤植の多いドキュメントだ。文章にさえなっていない箇所もあり、意外と翻訳しづらい :$。日本語版は可能は分かる範囲で修正しているけど。
See Also GIO リファレンスマニュアル: v2.18.4 版の API リファレンス
See Also SVN リポジトリ: 翻訳作業の SVN リポジトリ
See Also GIO Reference Manual: オリジナルのドキュメント
See Also バグ報告と追跡: 翻訳バグなどの報告はこちらへどうぞ
See Also 前バージョンのドキュメント: その他関連するドキュメント一覧