cookbook: Add a recipe on how to create sub-textures

Fiddle with Cogl textures to create a new ClutterTexture that only
displays a rectangular region of a bigger ClutterTexture.
This commit is contained in:
Damien Lespiau
2010-08-05 10:58:42 +01:00
parent ad1f1cb741
commit cbd6e047dd
9 changed files with 394 additions and 8 deletions

View File

@ -1,3 +1,5 @@
/animations-rotating
/text-shadow
/textures-reflection
/animations-rotating
/textures-split-go
/textures-sub-texture

View File

@ -3,9 +3,11 @@ include $(top_srcdir)/build/autotools/Makefile.am.silent
NULL =
noinst_PROGRAMS = \
textures-reflection \
animations-rotating \
text-shadow \
animations-rotating \
textures-reflection \
textures-split-go \
textures-sub-texture \
$(NULL)
INCLUDES = \
@ -27,8 +29,8 @@ AM_CFLAGS = \
AM_LDFLAGS = $(CLUTTER_LIBS)
textures_reflection_SOURCES = textures-reflection.c
text_shadow_SOURCES = text-shadow.c
animations_rotating_SOURCE = animations-rotating.c
animations_rotating_SOURCES = animations-rotating.c
text_shadow_SOURCES = text-shadow.c
textures_reflection_SOURCES = textures-reflection.c
textures_split_go_SOURCES = textures-split-go.c
textures_sub_texture_SOURCES = textures-sub-texture.c

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

View File

@ -0,0 +1,184 @@
#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;
}

View File

@ -0,0 +1,60 @@
#include <clutter/clutter.h>
int
main (int argc, char **argv)
{
ClutterActor *stage, *image, *sub_image;
CoglHandle texture, sub_texture;
gfloat image_width, image_height;
/* Initialize Clutter */
clutter_init (NULL, NULL);
/* Get the default stage */
stage = clutter_stage_get_default ();
clutter_stage_set_title (CLUTTER_STAGE (stage), "Sub-texture");
/* Create a new ClutterTexture that shows smiley.png */
image = clutter_texture_new_from_file ("smiley.png", NULL);
clutter_actor_get_size (image, &image_width, &image_height);
clutter_actor_set_size (stage,
image_width * 3 / 2 + 30,
image_height + 20);
/* Grab the CoglHandle of the underlying Cogl texture */
texture = clutter_texture_get_cogl_texture (CLUTTER_TEXTURE (image));
/* Create a new Cogl texture from the handle above. That new texture is a
* rectangular region from image, more precisely the north ouest corner
* of the image */
sub_texture = cogl_texture_new_from_sub_texture (texture,
0, 0,
image_width / 2,
image_height / 2);
/* Finally, use the newly created Cogl texture to feed a new ClutterTexture
* and thus create a new actor that displays sub_texture */
sub_image = clutter_texture_new ();
clutter_texture_set_cogl_texture (CLUTTER_TEXTURE (sub_image), sub_texture);
/*
* You could have used the more straightforward g_object_new() function that
* can create an object and set some properties on it at the same time:
* sub_image = g_object_new (CLUTTER_TYPE_TEXTURE,
* "cogl-texture", sub_texture,
* NULL);
*/
/* Put the original image at (10,10) and the new sub image next to it */
clutter_actor_set_position (image, 10, 10);
clutter_actor_set_position (sub_image, 20 + image_width, 10);
/* Add both ClutterTexture to the stage */
clutter_container_add (CLUTTER_CONTAINER (stage), image, sub_image, NULL);
clutter_actor_show_all (stage);
clutter_main ();
return 0;
}