今回は 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 ってもっと面倒なイメージがあったのにな。