1 #include <stdlib.h>
2 #include <clutter/clutter.h>
3
4 /* pixels between the source and its reflection */
5 #define V_PADDING 4
6
7 static void
_clone_paint_cb(ClutterActor * actor)8 _clone_paint_cb (ClutterActor *actor)
9 {
10 ClutterActor *source;
11 ClutterActorBox box;
12 CoglHandle material;
13 gfloat width, height;
14 guint8 opacity;
15 CoglColor color_1, color_2;
16 CoglTextureVertex vertices[4];
17
18 /* if we don't have a source actor, don't paint */
19 source = clutter_clone_get_source (CLUTTER_CLONE (actor));
20 if (source == NULL)
21 goto out;
22
23 /* if the source texture does not have any content, don't paint */
24 material = clutter_texture_get_cogl_material (CLUTTER_TEXTURE (source));
25 if (material == NULL)
26 goto out;
27
28 /* get the size of the reflection */
29 clutter_actor_get_allocation_box (actor, &box);
30 clutter_actor_box_get_size (&box, &width, &height);
31
32 /* get the composite opacity of the actor */
33 opacity = clutter_actor_get_paint_opacity (actor);
34
35 /* figure out the two colors for the reflection: the first is
36 * full color and the second is the same, but at 0 opacity
37 */
38 cogl_color_init_from_4f (&color_1, 1.0, 1.0, 1.0, opacity / 255.);
39 cogl_color_premultiply (&color_1);
40 cogl_color_init_from_4f (&color_2, 1.0, 1.0, 1.0, 0.0);
41 cogl_color_premultiply (&color_2);
42
43 /* now describe the four vertices of the quad; since it has
44 * to be a reflection, we need to invert it as well
45 */
46 vertices[0].x = 0; vertices[0].y = 0; vertices[0].z = 0;
47 vertices[0].tx = 0.0; vertices[0].ty = 1.0;
48 vertices[0].color = color_1;
49
50 vertices[1].x = width; vertices[1].y = 0; vertices[1].z = 0;
51 vertices[1].tx = 1.0; vertices[1].ty = 1.0;
52 vertices[1].color = color_1;
53
54 vertices[2].x = width; vertices[2].y = height; vertices[2].z = 0;
55 vertices[2].tx = 1.0; vertices[2].ty = 0.0;
56 vertices[2].color = color_2;
57
58 vertices[3].x = 0; vertices[3].y = height; vertices[3].z = 0;
59 vertices[3].tx = 0.0; vertices[3].ty = 0.0;
60 vertices[3].color = color_2;
61
62 /* paint the same texture but with a different geometry */
63 cogl_set_source (material);
64 cogl_polygon (vertices, 4, TRUE);
65
66 out:
67 /* prevent the default clone handler from running */
68 g_signal_stop_emission_by_name (actor, "paint");
69 }
70
71 int
main(int argc,char * argv[])72 main (int argc, char *argv[])
73 {
74 ClutterActor *stage;
75 ClutterActor *texture;
76 GError *error = NULL;
77 ClutterActor *clone;
78 gfloat y_offset;
79
80 if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS)
81 return 1;
82
83 stage = clutter_stage_new ();
84 clutter_stage_set_title (CLUTTER_STAGE (stage), "Reflection");
85 g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL);
86
87 texture = clutter_texture_new ();
88 clutter_texture_set_from_file (CLUTTER_TEXTURE (texture),
89 "redhand.png",
90 &error);
91 clutter_actor_add_constraint (texture, clutter_align_constraint_new (stage, CLUTTER_ALIGN_X_AXIS, 0.5));
92 clutter_actor_add_constraint (texture, clutter_align_constraint_new (stage, CLUTTER_ALIGN_Y_AXIS, 0.2));
93
94 y_offset = clutter_actor_get_height (texture) + V_PADDING;
95
96 clone = clutter_clone_new (texture);
97 clutter_actor_add_constraint (clone, clutter_bind_constraint_new (texture, CLUTTER_BIND_X, 0.0));
98 clutter_actor_add_constraint (clone, clutter_bind_constraint_new (texture, CLUTTER_BIND_Y, y_offset));
99 g_signal_connect (clone,
100 "paint",
101 G_CALLBACK (_clone_paint_cb),
102 NULL);
103
104 clutter_container_add (CLUTTER_CONTAINER (stage), texture, clone, NULL);
105
106 clutter_actor_show (stage);
107
108 clutter_main ();
109
110 return EXIT_SUCCESS;
111 }
112