Clutter を回転させてみる
Clutter-1.12.0 から回転方法が変更されています。以前は x,y 軸の回転と z 軸の回転は別の関数だったのですが、今回からは全部同じ clutter_actor_set_rotation_angle() という関数になっていて、 回転する ClutterActor 、回転軸、回転角度を指定します。回転の中心は pivot-point と pivot-point-z になるようで、それぞれ clutter_actor_set_pivot_point() と clutter_actor_set_pivot_point_z() で指定するようです。z 無しは、 0.0 から 1.0 の正規化した値(縦横を1とする)にするみたいですが、 z 付きは z 軸に沿った距離とマニュアルに書かれています。指定しなければ、デフォルトは 0.0 になっているようです。今回は指定せずに、ぐるぐる回してみます。
まずは C です。
#include <clutter/clutter.h> void on_completed (ClutterTimeline *timeline, gpointer user_data) { ClutterActor *actor; gdouble angle; static ClutterRotateAxis axis = CLUTTER_X_AXIS; actor = * (ClutterActor**)user_data; clutter_actor_save_easing_state (actor); angle = clutter_actor_get_rotation_angle (actor, axis); angle += 30; if (angle >= 360) angle = 0; clutter_actor_set_rotation_angle (actor, axis, angle); if (axis == CLUTTER_X_AXIS) axis = CLUTTER_Y_AXIS; else if (axis == CLUTTER_Y_AXIS) axis = CLUTTER_Z_AXIS; else axis = CLUTTER_X_AXIS; clutter_actor_restore_easing_state (actor); } int main (int argc, char *argv[]) { ClutterStage *stage; ClutterActor *actor; ClutterTimeline *timeline; if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS) return 1; stage = (ClutterStage*) clutter_stage_new (); g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL); actor = clutter_actor_new (); clutter_actor_set_background_color (actor, clutter_color_get_static (CLUTTER_COLOR_RED)); clutter_actor_set_size (actor, 100, 100); clutter_actor_set_position (actor, 100, 100); timeline = clutter_timeline_new (1000); clutter_timeline_set_repeat_count (timeline, -1); g_signal_connect (timeline, "completed", G_CALLBACK (on_completed), &actor); clutter_timeline_start (timeline); clutter_actor_add_child ((ClutterActor*) stage, actor); clutter_actor_show ((ClutterActor*) stage); clutter_main (); return 0; }
説明するまでもなく、 1000ms 単位でぐるぐる回ります。easing_state を使っているので、アニメーションになっています。 360度のときは 0度にするので、その時に一気に変化するのが解ると思います。
次は Gjs ですが、こちらもソースだけで説明はしません。
#! /usr/bin/env gjs const Clutter = imports.gi.Clutter; let axis = Clutter.RotateAxis.X_AXIS; function on_completed (timeline) { actor.save_easing_state(); angle = actor.get_rotation_angle(axis); angle += 30; if (angle >= 360) angle = 0; actor.set_rotation_angle(axis, angle); if (axis == Clutter.RotateAxis.X_AXIS) axis = Clutter.RotateAxis.Y_AXIS; else if (axis == Clutter.RotateAxis.Y_AXIS) axis = Clutter.RotateAxis.Z_AXIS; else axis = Clutter.RotateAxis.X_AXIS; actor.restore_easing_state(); } Clutter.init(null); let stage = new Clutter.Stage(); stage.connect('destroy', Clutter.main_quit); let actor = new Clutter.Actor(); actor.set_background_color(Clutter.Color.get_static (Clutter.StaticColor.RED)); actor.set_size(100, 100); actor.set_position(100, 100); let timeline = new Clutter.Timeline({duration:1000}); timeline.set_repeat_count(-1); timeline.connect('completed', on_completed); timeline.start(); stage.add_child(actor); stage.show(); Clutter.main();