mutter/doc/cookbook/examples/textures-split-go.c

187 lines
6.9 KiB
C
Raw Normal View History

#include <clutter/clutter.h>
/* Context will be used to carry interesting variables between functions */
typedef struct
{
ClutterActor *sub_nw, *sub_ne, *sub_sw, *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_nw, 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_sw, 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 G_SOURCE_REMOVE; /* 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_nw, &x, &y);
clutter_actor_animate (context->sub_nw, 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_sw, &x, &y);
clutter_actor_animate (context->sub_sw, 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! */
clutter_threads_add_timeout (500, go_away, context);
return G_SOURCE_REMOVE; /* 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;
if (clutter_init (NULL, NULL) != CLUTTER_INIT_SUCCESS)
return 1;
stage = clutter_stage_new ();
clutter_actor_get_size (stage, &stage_width, &stage_height);
clutter_stage_set_title (CLUTTER_STAGE (stage), "Animate sub-textures");
g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL);
/* 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_nw = 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_sw = 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_nw,
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_sw,
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_nw,
context.sub_ne, context.sub_sw, 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! */
clutter_threads_add_timeout (2000, split, &context);
clutter_main ();
return 0;
}