mutter/doc/cookbook/examples/textures-reflection.c

111 lines
3.5 KiB
C
Raw Normal View History

#include <stdlib.h>
#include <clutter/clutter.h>
/* pixels between the source and its reflection */
#define V_PADDING 4
static void
_clone_paint_cb (ClutterActor *actor)
{
ClutterActor *source;
ClutterActorBox box;
CoglHandle material;
gfloat width, height;
guint8 opacity;
CoglColor color_1, color_2;
CoglTextureVertex vertices[4];
/* if we don't have a source actor, don't paint */
source = clutter_clone_get_source (CLUTTER_CLONE (actor));
if (source == NULL)
goto out;
/* if the source texture does not have any content, don't paint */
material = clutter_texture_get_cogl_material (CLUTTER_TEXTURE (source));
if (material == NULL)
goto out;
/* get the size of the reflection */
clutter_actor_get_allocation_box (actor, &box);
clutter_actor_box_get_size (&box, &width, &height);
/* get the composite opacity of the actor */
opacity = clutter_actor_get_paint_opacity (actor);
/* figure out the two colors for the reflection: the first is
* full color and the second is the same, but at 0 opacity
*/
cogl_color_init_from_4f (&color_1, 1.0, 1.0, 1.0, opacity / 255.);
cogl_color_premultiply (&color_1);
cogl_color_init_from_4f (&color_2, 1.0, 1.0, 1.0, 0.0);
cogl_color_premultiply (&color_2);
/* now describe the four vertices of the quad; since it has
* to be a reflection, we need to invert it as well
*/
vertices[0].x = 0; vertices[0].y = 0; vertices[0].z = 0;
vertices[0].tx = 0.0; vertices[0].ty = 1.0;
vertices[0].color = color_1;
vertices[1].x = width; vertices[1].y = 0; vertices[1].z = 0;
vertices[1].tx = 1.0; vertices[1].ty = 1.0;
vertices[1].color = color_1;
vertices[2].x = width; vertices[2].y = height; vertices[2].z = 0;
vertices[2].tx = 1.0; vertices[2].ty = 0.0;
vertices[2].color = color_2;
vertices[3].x = 0; vertices[3].y = height; vertices[3].z = 0;
vertices[3].tx = 0.0; vertices[3].ty = 0.0;
vertices[3].color = color_2;
/* paint the same texture but with a different geometry */
cogl_set_source (material);
cogl_polygon (vertices, 4, TRUE);
out:
/* prevent the default clone handler from running */
g_signal_stop_emission_by_name (actor, "paint");
}
int
main (int argc, char *argv[])
{
ClutterActor *stage;
ClutterActor *texture;
GError *error = NULL;
ClutterActor *clone;
gfloat y_offset;
clutter_init (&argc, &argv);
stage = clutter_stage_new ();
clutter_stage_set_title (CLUTTER_STAGE (stage), "Reflection");
g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL);
texture = clutter_texture_new ();
clutter_texture_set_from_file (CLUTTER_TEXTURE (texture),
TESTS_DATA_DIR "/redhand.png",
&error);
clutter_actor_add_constraint (texture, clutter_align_constraint_new (stage, CLUTTER_ALIGN_X_AXIS, 0.5));
clutter_actor_add_constraint (texture, clutter_align_constraint_new (stage, CLUTTER_ALIGN_Y_AXIS, 0.2));
y_offset = clutter_actor_get_height (texture) + V_PADDING;
clone = clutter_clone_new (texture);
clutter_actor_add_constraint (clone, clutter_bind_constraint_new (texture, CLUTTER_BIND_X, 0.0));
clutter_actor_add_constraint (clone, clutter_bind_constraint_new (texture, CLUTTER_BIND_Y, y_offset));
g_signal_connect (clone,
"paint",
G_CALLBACK (_clone_paint_cb),
NULL);
clutter_container_add (CLUTTER_CONTAINER (stage), texture, clone, NULL);
clutter_actor_show (stage);
clutter_main ();
return EXIT_SUCCESS;
}