cookbook/examples: Don't mix up height and width while splitting
[profile/ivi/clutter.git] / doc / cookbook / examples / textures-split-go.c
1 #include <clutter/clutter.h>
2
3 /* Context will be used to carry interesting variables between functions */
4 typedef struct
5 {
6   ClutterActor *sub_nw, *sub_ne, *sub_sw, *sub_se;
7   gfloat image_width, image_height;
8 } Context;
9
10 /* Here, we animate the texture to go way by giving the new coordinates
11  * outside of the stage. We rotate the sub-textures around their anchor
12  * point (set in setup_sub() as well, it looks cool. */
13 static gboolean
14 go_away (gpointer data)
15 {
16   Context *context = data;
17
18   clutter_actor_animate (context->sub_nw, CLUTTER_EASE_OUT_CUBIC, 1500,
19                          "x", -context->image_width,
20                          "y", -context->image_height,
21                          "rotation-angle-z", 2000.,
22                          NULL);
23   clutter_actor_animate (context->sub_ne, CLUTTER_EASE_OUT_CUBIC, 1500,
24                          "x", +context->image_width,
25                          "y", -context->image_height,
26                          "rotation-angle-z", 2000.,
27                          NULL);
28   clutter_actor_animate (context->sub_sw, CLUTTER_EASE_OUT_CUBIC, 1500,
29                          "x", -context->image_width,
30                          "y", +context->image_height,
31                          "rotation-angle-z", 2000.,
32                          NULL);
33   clutter_actor_animate (context->sub_se, CLUTTER_EASE_OUT_CUBIC, 1500,
34                          "x", -context->image_width,
35                          "y", +context->image_height,
36                          "rotation-angle-z", 2000.,
37                          NULL);
38   return G_SOURCE_REMOVE; /* remove the timeout source */
39 }
40
41 /* We split the four sub-textures faking to be the big texture, moving them
42  * away by 10 pixels in each direction */
43 static gboolean
44 split (gpointer data)
45 {
46   Context *context = data;
47   gfloat x, y;
48
49   clutter_actor_get_position (context->sub_nw, &x, &y);
50   clutter_actor_animate (context->sub_nw, CLUTTER_EASE_OUT_CUBIC, 300,
51                          "x", x - 10,
52                          "y", y - 10,
53                          NULL);
54   clutter_actor_get_position (context->sub_ne, &x, &y);
55   clutter_actor_animate (context->sub_ne, CLUTTER_EASE_OUT_CUBIC, 300,
56                          "x", x + 10,
57                          "y", y - 10,
58                          NULL);
59   clutter_actor_get_position (context->sub_sw, &x, &y);
60   clutter_actor_animate (context->sub_sw, CLUTTER_EASE_OUT_CUBIC, 300,
61                          "x", x - 10,
62                          "y", y + 10,
63                          NULL);
64   clutter_actor_get_position (context->sub_se, &x, &y);
65   clutter_actor_animate (context->sub_se, CLUTTER_EASE_OUT_CUBIC, 300,
66                          "x", x + 10,
67                          "y", y + 10,
68                          NULL);
69
70   /* In 500ms the textures will flee! */
71   clutter_threads_add_timeout (500, go_away, context);
72
73   return G_SOURCE_REMOVE; /* remove the timeout source */
74 }
75
76 static ClutterActor *
77 setup_sub (CoglHandle texture,
78            gint       image_width,
79            gint       image_height,
80            gint       t_x,
81            gint       t_y,
82            gint       t_width,
83            gint       t_height)
84 {
85   CoglHandle sub_texture;
86   ClutterActor *sub_image;
87
88   /* Create a new sub-texture from textures */
89   sub_texture = cogl_texture_new_from_sub_texture (texture,
90                                                    t_x, t_y,
91                                                    t_width, t_height);
92
93   /* Create the corresponding ClutterTexture */
94   sub_image = g_object_new (CLUTTER_TYPE_TEXTURE,
95                             "cogl-texture", sub_texture,
96                             NULL);
97
98   /* Set the anchor point in the middle of each sub_image so the position and
99    * rotation of the textures are relative to that point */
100   clutter_actor_set_anchor_point (sub_image, image_width / 4, image_height / 4);
101
102   return sub_image;
103 }
104
105 #define IMAGE "smiley.png"
106
107 int
108 main (int    argc,
109       char **argv)
110 {
111   gfloat image_width, image_height, stage_width, stage_height;
112   ClutterActor *stage, *image;
113   GError *error = NULL;
114   CoglHandle texture;
115   Context context;
116
117   if (clutter_init (NULL, NULL) != CLUTTER_INIT_SUCCESS)
118     return 1;
119
120   stage = clutter_stage_new ();
121   clutter_actor_get_size (stage, &stage_width, &stage_height);
122   clutter_stage_set_title (CLUTTER_STAGE (stage), "Animate sub-textures");
123   g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL);
124
125   /* Load smiley.png, creating a new ClutterTexture, get its size and the
126    * Cogl texture handle */
127   image = clutter_texture_new_from_file (IMAGE, &error);
128   if (error != NULL)
129     {
130       g_warning ("Could not load " IMAGE ": %s", error->message);
131       g_clear_error (&error);
132       return 1;
133     }
134   clutter_actor_get_size (image, &image_width, &image_height);
135   texture = clutter_texture_get_cogl_texture (CLUTTER_TEXTURE (image));
136
137   /* Create four sub-textures from image, actually splitting the image in
138    * four */
139   context.sub_nw = setup_sub (texture, image_width, image_height,
140                               0, 0, image_width / 2 , image_height / 2);
141   context.sub_ne = setup_sub (texture, image_width, image_height,
142                               image_width / 2 , 0,
143                               image_width / 2, image_height / 2);
144   context.sub_sw = setup_sub (texture, image_width, image_height,
145                               0.f, image_height / 2,
146                               image_width / 2, image_height / 2);
147   context.sub_se = setup_sub (texture, image_width, image_height,
148                               image_width / 2, image_height / 2,
149                               image_width / 2, image_height / 2);
150
151   /* We don't need the image anymore as we won't display it and as
152    * cogl_texture_new_from_sub_texture() keeps a reference to the underlying
153    * texture ressource */
154   g_object_unref (image);
155
156   /* Position the sub-texures in the middle of the screen, recreating the
157    * original texture */
158   clutter_actor_set_position (context.sub_nw,
159                               stage_width / 2 - image_width / 4,
160                               stage_height / 2 - image_height / 4);
161   clutter_actor_set_position (context.sub_ne,
162                               stage_width / 2 + image_width / 4,
163                               stage_height / 2 - image_height / 4);
164   clutter_actor_set_position (context.sub_sw,
165                               stage_width / 2 - image_width / 4,
166                               stage_height / 2 + image_height / 4);
167   clutter_actor_set_position (context.sub_se,
168                               stage_width / 2 + image_width / 4,
169                               stage_height / 2 + image_height / 4);
170
171   /* Add the four sub-textures to the stage */
172   clutter_container_add (CLUTTER_CONTAINER (stage), context.sub_nw,
173                          context.sub_ne, context.sub_sw, context.sub_se, NULL);
174
175   clutter_actor_show_all (stage);
176
177   context.image_width = image_width;
178   context.image_height = image_height;
179
180   /* In two seconds, we'll split the texture! */
181   clutter_threads_add_timeout (2000, split, &context);
182
183   clutter_main ();
184
185   return 0;
186 }