今回は Clutter で画像をクルクル回してみよう。
3D ライブラリの定番ですね、ClutterImage を使うようだ。
ClutterImage: Clutter Reference Manual
画像ファイルをセットする方法は公式のサンプルコードがある。
コレを clutter_actor_set_content すればテクスチャになるってことかな。
画像の原寸と ClutterActor のサイズはどんな関係なんだろう。
チャチャッと実験コードを書いて試してみよう。
このサンプルを作っている時に気が付いたけど ClutterScore は deprecated だ。
CLutterTimeline に同様の property がある時点で気が付けよって感じですが。
#!/usr/bin/gjs
const Clutter = imports.gi.Clutter;
const GdkPixbuf = imports.gi.GdkPixbuf;
const Cogl = imports.gi.Cogl;
const Lang = imports.lang;
// Own Rewrite
const FILENAME = "/home/sasakima-nao/pic/game/gf/nae_yuki_ssr/ [ハロウィン13]優木苗.jpg";
const ImageTest = new Lang.Class({
Name: 'ImageTest',
Extends: Clutter.Stage,
_init: function() {
this.parent();
// Image
let image = new Clutter.Image();
let pixbuf = GdkPixbuf.Pixbuf.new_from_file(FILENAME);
let alpha = pixbuf.get_has_alpha() ? Cogl.PixelFormat.RGBA_8888 : Cogl.PixelFormat.RGB_888;
image.set_data(
pixbuf.get_pixels(),
alpha,
pixbuf.get_width(),
pixbuf.get_height(),
pixbuf.get_rowstride
);
// Rotate Actor
this.actor = new Clutter.Actor();
this.actor.set_pivot_point(0.5, 0.5);
let xy = pixbuf.get_height() / pixbuf.get_width();
this.actor.set_size(200, 200 * xy);
this.actor.set_position(70, 50);
this.actor.set_content(image);
// Timer
this.timeline = new Clutter.Timeline({
duration: 100,
loop: true
});
this.rotation = 0;
this.timeline.connect("new-frame", Lang.bind(this, function() {
this.rotation += 0.3
this.actor.set_rotation_angle(Clutter.RotateAxis.Y_AXIS, this.rotation);
this.actor.set_rotation_angle(Clutter.RotateAxis.Z_AXIS, this.rotation);
}));
this.timeline.start();
// this
this.add_child(this.actor);
this.connect("hide", Clutter.main_quit);
//this.set_user_resizable(true);
this.show_all();
}
});
Clutter.init(null);
new ImageTest();
Clutter.main();
公式サンプルの方法で画像全体のデータは取り込めるようだ。
ClutterActor の大きさに合わせてアスペクト比無視で拡縮される。
上記は一応大雑把にアスペクト比を合わせるようにしている。
PivotPoint や回転は全部 ClutterActor 側の仕事。
ClutterImage は ClutterActor の角度に合わせてレンダリングされる。
簡単すぎて拍子抜け、3D ってもっと面倒なイメージがあったのにな。
