mirror of
https://github.com/brl/mutter.git
synced 2024-11-11 00:26:40 -05:00
c230fd8dfd
Modified the code example for the Clutter API version of the cross-fade to use the same command line as the COGL version. This also simplifies the explanation in the recipe. Also made the COGL code sample more consistent with the Clutter API code sample.
164 lines
5.2 KiB
C
164 lines
5.2 KiB
C
#include <stdlib.h>
|
|
#include <clutter/clutter.h>
|
|
|
|
static gchar *source = NULL;
|
|
static gchar *target = NULL;
|
|
static guint duration = 1000;
|
|
|
|
static GOptionEntry entries[] = {
|
|
{
|
|
"source", 's',
|
|
0,
|
|
G_OPTION_ARG_FILENAME, &source,
|
|
"The source image of the cross-fade", "FILE"
|
|
},
|
|
{
|
|
"target", 't',
|
|
0,
|
|
G_OPTION_ARG_FILENAME, &target,
|
|
"The target image of the cross-fade", "FILE"
|
|
},
|
|
{
|
|
"duration", 'd',
|
|
0,
|
|
G_OPTION_ARG_INT, &duration,
|
|
"The duration of the cross-fade, in milliseconds", "MSECS"
|
|
},
|
|
|
|
{ NULL }
|
|
};
|
|
|
|
static void
|
|
_update_progress_cb (ClutterTimeline *timeline,
|
|
guint elapsed_msecs,
|
|
ClutterTexture *texture)
|
|
{
|
|
CoglHandle material = clutter_texture_get_cogl_material (texture);
|
|
if (material == COGL_INVALID_HANDLE)
|
|
return;
|
|
|
|
/* You should assume that a material can only be modified once, after
|
|
* its creation; if you need to modify it later you should use a copy
|
|
* instead. Cogl makes copying materials reasonably cheap
|
|
*/
|
|
CoglHandle copy = cogl_material_copy (material);
|
|
|
|
gdouble progress = clutter_timeline_get_progress (timeline);
|
|
|
|
/* Create the constant color to be used when combining the two
|
|
* material layers; we use a black color with an alpha component
|
|
* depending on the current progress of the timeline
|
|
*/
|
|
CoglColor constant;
|
|
cogl_color_set_from_4ub (&constant, 0x00, 0x00, 0x00, 0xff * progress);
|
|
|
|
/* This sets the value of the constant color we use when combining
|
|
* the two layers
|
|
*/
|
|
cogl_material_set_layer_combine_constant (copy, 1, &constant);
|
|
|
|
/* The Texture now owns the material */
|
|
clutter_texture_set_cogl_material (texture, copy);
|
|
cogl_handle_unref (copy);
|
|
|
|
clutter_actor_queue_redraw (CLUTTER_ACTOR (texture));
|
|
}
|
|
|
|
static CoglHandle
|
|
load_cogl_texture (const char *type,
|
|
const char *file)
|
|
{
|
|
GError *error = NULL;
|
|
|
|
CoglHandle retval = cogl_texture_new_from_file (file,
|
|
COGL_TEXTURE_NO_SLICING,
|
|
COGL_PIXEL_FORMAT_ANY,
|
|
&error);
|
|
if (error != NULL)
|
|
{
|
|
g_print ("Unable to load %s image: %s\n", type, error->message);
|
|
g_error_free (error);
|
|
exit (EXIT_FAILURE);
|
|
}
|
|
|
|
return retval;
|
|
}
|
|
|
|
static int
|
|
print_usage_and_exit (const char *exec_name,
|
|
int exit_code)
|
|
{
|
|
g_print ("Usage: %s -s <source> -t <target> [-d <duration>]\n", exec_name);
|
|
return exit_code;
|
|
}
|
|
|
|
int
|
|
main (int argc, char *argv[])
|
|
{
|
|
clutter_init_with_args (&argc, &argv,
|
|
" - Crossfade", entries,
|
|
NULL,
|
|
NULL);
|
|
|
|
if (source == NULL || target == NULL)
|
|
return print_usage_and_exit (argv[0], EXIT_FAILURE);
|
|
|
|
/* Load the source and target images using Cogl, because we need
|
|
* to combine them into the same ClutterTexture.
|
|
*/
|
|
CoglHandle texture_1 = load_cogl_texture ("source", source);
|
|
CoglHandle texture_2 = load_cogl_texture ("target", target);
|
|
|
|
/* Create a new Cogl material holding the two textures inside two
|
|
* separate layers.
|
|
*/
|
|
CoglHandle material = cogl_material_new ();
|
|
cogl_material_set_layer (material, 1, texture_1);
|
|
cogl_material_set_layer (material, 0, texture_2);
|
|
|
|
/* Set the layer combination description for the second layer; the
|
|
* default for Cogl is to simply multiply the layer with the
|
|
* precendent one. In this case we interpolate the color for each
|
|
* pixel between the pixel value of the previous layer and the
|
|
* current one, using the alpha component of a constant color as
|
|
* the interpolation factor.
|
|
*/
|
|
cogl_material_set_layer_combine (material, 1,
|
|
"RGBA = INTERPOLATE (PREVIOUS, "
|
|
"TEXTURE, "
|
|
"CONSTANT[A])",
|
|
NULL);
|
|
|
|
/* The material now owns the two textures */
|
|
cogl_handle_unref (texture_1);
|
|
cogl_handle_unref (texture_2);
|
|
|
|
/* Create a Texture and place it in the middle of the stage; then
|
|
* assign the material we created earlier to the Texture for painting
|
|
* it
|
|
*/
|
|
ClutterActor *stage = clutter_stage_get_default ();
|
|
clutter_stage_set_title (CLUTTER_STAGE (stage), "cross-fade");
|
|
clutter_actor_set_size (stage, 600, 600);
|
|
clutter_actor_show (stage);
|
|
g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL);
|
|
|
|
ClutterActor *texture = clutter_texture_new ();
|
|
clutter_container_add_actor (CLUTTER_CONTAINER (stage), texture);
|
|
clutter_texture_set_cogl_material (CLUTTER_TEXTURE (texture), material);
|
|
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.5));
|
|
cogl_handle_unref (material);
|
|
|
|
/* The timeline will drive the cross-fading */
|
|
ClutterTimeline *timeline = clutter_timeline_new (duration);
|
|
g_signal_connect (timeline, "new-frame", G_CALLBACK (_update_progress_cb), texture);
|
|
clutter_timeline_start (timeline);
|
|
|
|
clutter_main ();
|
|
|
|
g_object_unref (timeline);
|
|
|
|
return EXIT_SUCCESS;
|
|
}
|