#include /* Context will be used to carry interesting variables between functions */ typedef struct { ClutterActor *sub_no, *sub_ne, *sub_so, *sub_se; gfloat image_width, image_height; } Context; /* Here, we animate the texture to go way by giving the new coordinates * outside of the stage. We rotate the sub-textures around their anchor * point (set in setup_sub() as well, it looks cool. */ static gboolean go_away (gpointer data) { Context *context = data; clutter_actor_animate (context->sub_no, CLUTTER_EASE_OUT_CUBIC, 1500, "x", -context->image_width, "y", -context->image_height, "rotation-angle-z", 2000., NULL); clutter_actor_animate (context->sub_ne, CLUTTER_EASE_OUT_CUBIC, 1500, "x", +context->image_width, "y", -context->image_height, "rotation-angle-z", 2000., NULL); clutter_actor_animate (context->sub_so, CLUTTER_EASE_OUT_CUBIC, 1500, "x", -context->image_width, "y", +context->image_height, "rotation-angle-z", 2000., NULL); clutter_actor_animate (context->sub_se, CLUTTER_EASE_OUT_CUBIC, 1500, "x", -context->image_width, "y", +context->image_height, "rotation-angle-z", 2000., NULL); return FALSE; /* remove the timeout source */ } /* We split the four sub-textures faking to be the big texture, moving them * away by 10 pixels in each direction */ static gboolean split (gpointer data) { Context *context = data; gfloat x, y; clutter_actor_get_position (context->sub_no, &x, &y); clutter_actor_animate (context->sub_no, CLUTTER_EASE_OUT_CUBIC, 300, "x", x - 10, "y", y - 10, NULL); clutter_actor_get_position (context->sub_ne, &x, &y); clutter_actor_animate (context->sub_ne, CLUTTER_EASE_OUT_CUBIC, 300, "x", x + 10, "y", y - 10, NULL); clutter_actor_get_position (context->sub_so, &x, &y); clutter_actor_animate (context->sub_so, CLUTTER_EASE_OUT_CUBIC, 300, "x", x - 10, "y", y + 10, NULL); clutter_actor_get_position (context->sub_se, &x, &y); clutter_actor_animate (context->sub_se, CLUTTER_EASE_OUT_CUBIC, 300, "x", x + 10, "y", y + 10, NULL); /* In 500ms the textures will flee! */ g_timeout_add (500, go_away, context); return FALSE; /* remove the timeout source */ } static ClutterActor * setup_sub (CoglHandle texture, gint image_width, gint image_height, gint t_x, gint t_y, gint t_width, gint t_height) { CoglHandle sub_texture; ClutterActor *sub_image; /* Create a new sub-texture from textures */ sub_texture = cogl_texture_new_from_sub_texture (texture, t_x, t_y, t_width, t_height); /* Create the corresponding ClutterTexture */ sub_image = g_object_new (CLUTTER_TYPE_TEXTURE, "cogl-texture", sub_texture, NULL); /* Set the anchor point in the middle of each sub_image so the position and * rotation of the textures are relative to that point */ clutter_actor_set_anchor_point (sub_image, image_width / 4, image_height / 4); return sub_image; } #define IMAGE "smiley.png" int main (int argc, char **argv) { gfloat image_width, image_height, stage_width, stage_height; ClutterActor *stage, *image; GError *error = NULL; CoglHandle texture; Context context; clutter_init (NULL, NULL); stage = clutter_stage_get_default (); clutter_actor_get_size (stage, &stage_width, &stage_height); clutter_stage_set_title (CLUTTER_STAGE (stage), "Animate sub-textures"); /* Load smiley.png, creating a new ClutterTexture, get its size and the * Cogl texture handle */ image = clutter_texture_new_from_file (IMAGE, &error); if (error != NULL) { g_warning ("Could not load " IMAGE ": %s", error->message); g_clear_error (&error); return 1; } clutter_actor_get_size (image, &image_width, &image_height); texture = clutter_texture_get_cogl_texture (CLUTTER_TEXTURE (image)); /* Create four sub-textures from image, actually splitting the image in * four */ context.sub_no = setup_sub (texture, image_width, image_height, 0, 0, image_width / 2 , image_width / 2); context.sub_ne = setup_sub (texture, image_width, image_height, image_width / 2 , 0, image_width / 2, image_width / 2); context.sub_so = setup_sub (texture, image_width, image_height, 0.f, image_width / 2, image_width / 2, image_width / 2); context.sub_se = setup_sub (texture, image_width, image_height, image_width / 2, image_width / 2, image_width / 2, image_width / 2); /* We don't need the image anymore as we won't display it and as * cogl_texture_new_from_sub_texture() keeps a reference to the underlying * texture ressource */ g_object_unref (image); /* Position the sub-texures in the middle of the screen, recreating the * original texture */ clutter_actor_set_position (context.sub_no, stage_width / 2 - image_width / 4, stage_height / 2 - image_height / 4); clutter_actor_set_position (context.sub_ne, stage_width / 2 + image_width / 4, stage_height / 2 - image_height / 4); clutter_actor_set_position (context.sub_so, stage_width / 2 - image_width / 4, stage_height / 2 + image_height / 4); clutter_actor_set_position (context.sub_se, stage_width / 2 + image_width / 4, stage_height / 2 + image_height / 4); /* Add the four sub-textures to the stage */ clutter_container_add (CLUTTER_CONTAINER (stage), context.sub_no, context.sub_ne, context.sub_so, context.sub_se, NULL); clutter_actor_show_all (stage); context.image_width = image_width; context.image_height = image_height; /* In two seconds, we'll split the texture! */ g_timeout_add_seconds (2, split, &context); clutter_main (); return 0; }