We have learned the basic usage of clutter, with a large example to review, example Source: http://www.openismus.com/documents/clutter_tutorial/0.9/docs/tutorial/html/sec-full-example.html
. This tutorial is based on clutter0.9 and requires minor changes on clutter1.0. The following is an example of rewriting in clutter1.0:
# Include <clutter/clutter. h>
# Include <stdlib. h>
Const gint maid = 390;
Const gint ELLIPSE_HEIGHT = 450;
Const gint IMAGE_HEIGHT = 100;
Double angle_step = 30;
ClutterTimeline * timeline_rotation = NULL, * timeline_moveup = NULL;
ClutterActor * label_filename = NULL;
ClutterBehaviour * behaviour_scale = NULL, * behaviour_path = NULL,
* Behaviour_opacity = NULL;
Typedef struct Item {
ClutterActor * actor;
ClutterBehaviour * ellipse_behaviour;
Gchar * filepath;
} Item;
Item * item_at_front = NULL;
GSList * list_items = 0;
Void rotate_all_until_item_is_at_front (Item * item );
Gdouble angle_in_360 (gdouble angle ){
Gdouble result = angle;
While (result >=360)
Result-= 360;
Return result;
}
Void on_foreach_clear_list_items (gpointer data, gpointer user_data)
{
If (data = NULL)
Return;
Item * item = (Item *) data;
/* We don't need to unref the actor because the floating reference was taken by the stage .*/
G_object_unref (item-> ellipse_behaviour );
G_free (item-> filepath );
G_free (item );
}
Void scale_texture_default (ClutterActor * texture ){
Int pixbuf_height = 0;
Clutter_texture_get_base_size (clutter_texture (texture), null,
& Pixbuf_height );
Const gdouble scale = pixbuf_height? Image_height/(gdouble) pixbuf_height: 0;
Clutter_actor_set_scale (texture, scale, scale );
}
Void load_images (const gchar * directory_path ){
G_return_if_fail (directory_path );
/* Clear any existing images :*/
G_slist_foreach (list_items, on_foreach_clear_list_items, null );
G_slist_free (list_items );
/* Create a new list :*/
List_items = NULL;
Gerror * error = NULL;
Gdir * dir = g_dir_open (directory_path, 0, & error );
If (error ){
G_warning ("g_dir_open () failed: % s/n", error-> message );
G_clear_error (& error );
Return;
}
Int I = 0;
Const gchar * filename = NULL;
While (filename = g_dir_read_name (dir ))! = NULL ){
Gchar * path = g_build_filename (directory_path, filename, NULL );
Printf ("% 2d % s/n", ++ I, path );
ClutterActor * actor = clutter_texture_new_from_file (path, NULL );
If (actor ){
Item * item = g_new0 (Item, 1 );
Item-> actor = actor;
Item-> filepath = g_strdup (path );
Scale_texture_default (item-> actor );
List_items = g_slist_append (list_items, item );
}
G_free (path );
}
Angle_step = 360.0/I;
Printf ("total % d image, angel step is %. 1f/n", I, angle_step );
}
Gboolean on_texture_button_press (ClutterActor * actor, ClutterEvent * event,
Gpointer user_data ){
If (timeline_rotation & clutter_timeline_is_playing (timeline_rotation )){
Printf ("on_texture_button_press (): ignoring/n ");
Return FALSE;
} Else {
Printf ("on_texture_button_press (): handling/n ");
}
Item * item = (Item *) user_data;
Rotate_all_until_item_is_at_front (item );
Return TRUE;
}
Void add_to_ellipse_behaviour (ClutterTimeline * timeline_rotation, gdouble start_angle, Item * item ){
G_return_if_fail (timeline_rotation );
Clutteralpha * alpha = clutter_alpha_new_full (timeline_rotation,
Clutter_ease_out_sine );
/* If start is equal to end, the behaviour will rotate by exacly 360 degrees .*/
Item-> ellipse_behaviour = clutter_behaviour_ellipse_new (alpha, 320, ellipse_y,/* x, y */
Ellipse_height, ellipse_height/* width, height */
, Clutter_rotate_cw,
Start_angle, start_angle );
Clutter_behaviour_ellipse_set_angle_tilt (clutter_behaviour_ellipse (item-> ellipse_behaviour ),
Clutter_x_axis,-90.0 );
Clutter_behaviour_apply (item-> ellipse_behaviour, item-> actor );
}
Void add_image_actors (ClutterActor * stage ){
Int x = 20;
Int y = 0;
Gdouble angle = 0;
GSList * list = list_items;
While (list ){
Item * item = (Item *) list-> data;
ClutterActor * actor = item-> actor;
Clutter_actor_set_position (actor, x, y );
Y + = 100;
Clutter_container_add_actor (clutter_container (stage), actor );
/* Allow the actor to emit events. By default only the stage does this .*/
Clutter_actor_set_reactive (actor, true );
G_signal_connect (actor, "button-press-Event ",
G_CALLBACK (on_texture_button_press), item );
While (angle >=360)
Angle-= 360;
Add_to_ellipse_behaviour (timeline_rotation, angle, item );
Angle + = angle_step;
List = g_slist_next (list );
}
}
Void on_timeline_moveup_completed (cluttertimeline * timeline, gpointer user_data)
{
/* Unref this timeline because we have now finished with it :*/
G_object_unref (timeline_moveup );
Timeline_moveup = NULL;
G_object_unref (behaviour_scale );
Behaviour_scale = NULL;
G_object_unref (behaviour_path );
Behaviour_path = NULL;
G_object_unref (behaviour_opacity );
Behaviour_opacity = NULL;
}
Void on_timeline_rotation_completed (ClutterTimeline * timeline, gpointer user_data ){
ClutterActor * actor = item_at_front-> actor;
Timeline_moveup = clutter_timeline_new (1200/* milliseconds */);
/* For Scaling */
ClutterAlpha * alpha = clutter_alpha_new_full (timeline_moveup, CLUTTER_EASE_OUT_SINE );
Gdouble scale_start = 0;
Clutter_actor_get_scale (actor, & scale_start, NULL );
Const gdouble scale_end = scale_start * 1.80;
Behaviour_scale = clutter_behaviour_scale_new (alpha, scale_start, scale_start, scale_end, scale_end );
Clutter_behaviour_apply (behaviour_scale, actor );
/* Move the item up the y axis :*/
ClutterKnot knots [2];
Knots [0]. x = clutter_actor_get_x (actor );
Knots [0]. y = clutter_actor_get_y (actor );
Knots [1]. x = knots [0]. x-80;
Knots [1]. y = knots [0]. y-255;
Printf ("move from (% d, % d) to (% d, % d)/n", knots [0]. x, knots [0]. y, knots [1]. x, knots [1]. y );
Behaviour_path = clutter_behaviour_path_new_with_knots (alpha, knots, G_N_ELEMENTS (knots ));
Clutter_behaviour_apply (behaviour_path, actor );
/* Show the file name */
Clutter_text_set_text (CLUTTER_TEXT (label_filename), item_at_front-> filepath );
Behaviour_opacity = clutter_behaviour_opacity_new (alpha, 0,255 );
Clutter_behaviour_apply (behaviour_opacity, label_filename );
/* After it complete unref the param */
G_signal_connect (timeline_moveup, "completed", G_CALLBACK (on_timeline_moveup_completed), NULL );
Clutter_timeline_start (timeline_moveup );
}
Void rotate_all_until_item_is_at_front (Item * item ){
G_return_if_fail (item );
Clutter_timeline_stop (timeline_rotation );
If (timeline_moveup! = NULL)
Clutter_timeline_stop (timeline_moveup );
Clutter_actor_set_opacity (label_filename, 0 );
/* Get the item's position in the list :*/
Const gint pos = g_slist_index (list_items, item );
Printf ("We want to show pos = % d/n", pos );
G_assert (pos! =-1 );
If (! Item_at_front & list_items)
Item_at_front = (Item *) list_items-> data;
Gint pos_front = 0;
If (item_at_front)
Pos_front = g_slist_index (list_items, item_at_front );
Printf ("Current front pos is % d/n", pos_front );
G_assert (pos_front! =-1 );
/* Calculate the end angle of the first item :*/
Const gdouble angle_front = 90;
Gdouble angle_start = angle_front-(angle_step * pos_front );
Angle_start = angle_in_360 (angle_start );
Gdouble angle_end = angle_front-(angle_step * pos );
Printf ("angle (%. 0f %. 0f)/n", angle_start, angle_end );
Gdouble angle_diff = 0;
GSList * list = list_items;
Gint I = 0;
While (list ){
Item * this_item = (item *) List-> data;
/* Reset its size :*/
Scale_texture_default (this_item-> actor );
Angle_start = angle_in_360 (angle_start );
Angle_end = angle_in_360 (angle_end );
If (item_at_front = item)
Angle_end plus = 360;
Angle_end = angle_in_360 (angle_end );
Clutter_behaviour_ellipse_set_angle_start (
CLUTTER_BEHAVIOUR_ELLIPSE (this_item-> ellipse_behaviour), angle_start );
Clutter_behaviour_ellipse_set_angle_end (
CLUTTER_BEHAVIOUR_ELLIPSE (this_item-> ellipse_behaviour), angle_end );
If (this_item = item ){
If (angle_start <angle_end)
Angle_diff = angle_end-angle_start;
Else
Angle_diff = 360-(angle_start-angle_end );
Printf ("debug: angle diff = % f/n", angle_diff );
}
// Printf ("% 2d angle %. 0f, %. 0f/n", ++ I, angle_start, angle_end );
Angle_end + = angle_step;
Angle_start + = angle_step;
List = g_slist_next (list );
}
Const Gint COUNT = g_slist_length (list_items );
Gint pos_to_move = count + pos_front-Pos;
If (pos_to_move> count)
Pos_to_move-= count;
Int duration = (INT) (5000.0/count * pos_to_move );
Printf ("old is % d want % d POs to move = % d duration = % d/N", pos_front, POs, pos_to_move, duration );
Clutter_timeline_set_duration (timeline_rotation, duration );
Item_at_front = item;
Clutter_timeline_start (timeline_rotation );
}
Int main (int argc, char * argv []) {
Clutter_init (& argc, & argv );
ClutterColor stage_color = {0xB0, 0xB0, 0xB0, 0xff };
ClutterActor * stage = clutter_stage_get_default ();
Clutter_actor_set_size (stage, 800,600 );
Clutter_stage_set_color (CLUTTER_STAGE (stage), & stage_color );
/* Create and add a label actor, hidden at first :*/
Label_filename = clutter_text_new ();
ClutterColor label_color = {0x00,0x00,0x00, 0xff };
Clutter_text_set_color (CLUTTER_TEXT (label_filename), & label_color );
Clutter_text_set_font_name (CLUTTER_TEXT (label_filename), "18 18 ");
Clutter_actor_set_position (label_filename, 10, 10 );
Clutter_actor_set_opacity (label_filename, 0 );
Clutter_container_add_actor (CLUTTER_CONTAINER (stage), label_filename );
/* Add a plane under the ellipse of images :*/
ClutterColor rect_color = {0xff, 0xff, 0xdf, 0xff};/* white */
ClutterActor * rect = clutter_rectangle_new_with_color (& rect_color );
Clutter_actor_set_height (rect, ELLIPSE_HEIGHT + 20 );
Clutter_actor_set_width (rect, clutter_actor_get_width (stages) + 100 );
Clutter_actor_set_position (rect,-(clutter_actor_get_width (rect)-clutter_actor_get_width (stage)/2,
ELLIPSE_Y + IMAGE_HEIGHT-(clutter_actor_get_height (rect)/2 ));
Clutter_actor_set_rotation (rect, CLUTTER_X_AXIS, 90.0, 0.0, (clutter_actor_get_height (rect)/2.0), 0.0 );
Clutter_container_add_actor (CLUTTER_CONTAINER (stage), rect );
Timeline_rotation = clutter_timeline_new (5000 );
G_signal_connect (timeline_rotation, "completed", G_CALLBACK (on_timeline_rotation_completed), NULL );
/* Add an actor for each image :*/
Load_images ("./images /");
Add_image_actors (stage );
If (list_items)
Rotate_all_until_item_is_at_front (Item *) list_items-> data );
Clutter_actor_show_all (stage );
Clutter_main ();
G_object_unref (timeline_rotation );
Return exit_success;
}