cbd6e047dd
Fiddle with Cogl textures to create a new ClutterTexture that only displays a rectangular region of a bigger ClutterTexture.
185 lines
6.8 KiB
C
185 lines
6.8 KiB
C
#include <clutter/clutter.h>
|
|
|
|
/* 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;
|
|
}
|