f8e9565482
The test-easing interactive demo for the high-level animation API is a bit "flat". Instead of using a Rectangle actor we should probably be using something more "interesting" -- like a CairoTexture with a gradient.
247 lines
7.9 KiB
C
247 lines
7.9 KiB
C
#include <stdlib.h>
|
|
#include <gmodule.h>
|
|
#include <clutter/clutter.h>
|
|
|
|
const struct {
|
|
const gchar *name;
|
|
ClutterAnimationMode mode;
|
|
} easing_modes[] = {
|
|
{ "linear", CLUTTER_LINEAR },
|
|
{ "easeInQuad", CLUTTER_EASE_IN_QUAD },
|
|
{ "easeOutQuad", CLUTTER_EASE_OUT_QUAD },
|
|
{ "easeInOutQuad", CLUTTER_EASE_IN_OUT_QUAD },
|
|
{ "easeInCubic", CLUTTER_EASE_IN_CUBIC },
|
|
{ "easeOutCubic", CLUTTER_EASE_OUT_CUBIC },
|
|
{ "easeInOutCubic", CLUTTER_EASE_IN_OUT_CUBIC },
|
|
{ "easeInQuart", CLUTTER_EASE_IN_QUART },
|
|
{ "easeOutQuart", CLUTTER_EASE_OUT_QUART },
|
|
{ "easeInOutQuart", CLUTTER_EASE_IN_OUT_QUART },
|
|
{ "easeInQuint", CLUTTER_EASE_IN_QUINT },
|
|
{ "easeOutQuint", CLUTTER_EASE_OUT_QUINT },
|
|
{ "easeInOutQuint", CLUTTER_EASE_IN_OUT_QUINT },
|
|
{ "easeInSine", CLUTTER_EASE_IN_SINE },
|
|
{ "easeOutSine", CLUTTER_EASE_OUT_SINE },
|
|
{ "easeInOutSine", CLUTTER_EASE_IN_OUT_SINE },
|
|
{ "easeInExpo", CLUTTER_EASE_IN_EXPO },
|
|
{ "easeOutExpo", CLUTTER_EASE_OUT_EXPO },
|
|
{ "easeInOutExpo", CLUTTER_EASE_IN_OUT_EXPO },
|
|
{ "easeInCirc", CLUTTER_EASE_IN_CIRC },
|
|
{ "easeOutCirc", CLUTTER_EASE_OUT_CIRC },
|
|
{ "easeInOutCirc", CLUTTER_EASE_IN_OUT_CIRC },
|
|
{ "easeInElastic", CLUTTER_EASE_IN_ELASTIC },
|
|
{ "easeOutElastic", CLUTTER_EASE_OUT_ELASTIC },
|
|
{ "easeInOutElastic", CLUTTER_EASE_IN_OUT_ELASTIC },
|
|
{ "easeInBack", CLUTTER_EASE_IN_BACK },
|
|
{ "easeOutBack", CLUTTER_EASE_OUT_BACK },
|
|
{ "easeInOutBack", CLUTTER_EASE_IN_OUT_BACK },
|
|
{ "easeInBounce", CLUTTER_EASE_IN_BOUNCE },
|
|
{ "easeOutBounce", CLUTTER_EASE_OUT_BOUNCE },
|
|
{ "easeInOutBounce", CLUTTER_EASE_IN_OUT_BOUNCE },
|
|
};
|
|
|
|
static const gint n_easing_modes = G_N_ELEMENTS (easing_modes);
|
|
static gint current_mode = 0;
|
|
|
|
static gint duration = 1;
|
|
static gboolean recenter = FALSE;
|
|
|
|
static ClutterActor *main_stage = NULL;
|
|
static ClutterActor *easing_mode_label = NULL;
|
|
|
|
static void
|
|
on_animation_completed (ClutterAnimation *animation,
|
|
ClutterActor *rectangle)
|
|
{
|
|
gfloat base_x, base_y;
|
|
gint cur_mode;
|
|
|
|
base_x = clutter_actor_get_width (main_stage) / 2;
|
|
base_y = clutter_actor_get_height (main_stage) / 2;
|
|
|
|
cur_mode = easing_modes[current_mode].mode;
|
|
|
|
clutter_actor_animate (rectangle, cur_mode, 150,
|
|
"x", base_x,
|
|
"y", base_y,
|
|
NULL);
|
|
}
|
|
|
|
static gboolean
|
|
on_button_press (ClutterActor *actor,
|
|
ClutterButtonEvent *event,
|
|
ClutterActor *rectangle)
|
|
{
|
|
if (event->button == 3)
|
|
{
|
|
gchar *text;
|
|
gfloat stage_width, stage_height;
|
|
gfloat label_width, label_height;
|
|
|
|
current_mode = (current_mode + 1 < n_easing_modes) ? current_mode + 1
|
|
: 0;
|
|
|
|
text = g_strdup_printf ("Easing mode: %s (%d of %d)\n"
|
|
"Right click to change the easing mode",
|
|
easing_modes[current_mode].name,
|
|
current_mode + 1,
|
|
n_easing_modes);
|
|
|
|
clutter_text_set_text (CLUTTER_TEXT (easing_mode_label), text);
|
|
g_free (text);
|
|
|
|
clutter_actor_get_size (main_stage,
|
|
&stage_width,
|
|
&stage_height);
|
|
clutter_actor_get_size (easing_mode_label,
|
|
&label_width,
|
|
&label_height);
|
|
|
|
clutter_actor_set_position (easing_mode_label,
|
|
stage_width - label_width - 10,
|
|
stage_height - label_height - 10);
|
|
}
|
|
else if (event->button == 1)
|
|
{
|
|
ClutterAnimation *animation;
|
|
ClutterAnimationMode cur_mode;
|
|
|
|
cur_mode = easing_modes[current_mode].mode;
|
|
|
|
animation =
|
|
clutter_actor_animate (rectangle, cur_mode, duration * 1000,
|
|
"x", event->x,
|
|
"y", event->y,
|
|
NULL);
|
|
|
|
if (recenter)
|
|
g_signal_connect_after (animation, "completed",
|
|
G_CALLBACK (on_animation_completed),
|
|
rectangle);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static ClutterActor *
|
|
make_bouncer (const ClutterColor *base_color,
|
|
gfloat width,
|
|
gfloat height)
|
|
{
|
|
ClutterActor *retval;
|
|
cairo_t *cr;
|
|
cairo_pattern_t *pattern;
|
|
gfloat radius = MAX (width, height);
|
|
|
|
retval = clutter_cairo_texture_new (width, height);
|
|
|
|
cr = clutter_cairo_texture_create (CLUTTER_CAIRO_TEXTURE (retval));
|
|
|
|
cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR);
|
|
cairo_paint (cr);
|
|
cairo_set_operator (cr, CAIRO_OPERATOR_ADD);
|
|
|
|
cairo_arc (cr, radius / 2, radius / 2, radius / 2, 0.0, 2.0 * G_PI);
|
|
|
|
pattern = cairo_pattern_create_radial (radius / 2, radius / 2, 0,
|
|
radius, radius, radius);
|
|
cairo_pattern_add_color_stop_rgba (pattern,
|
|
0,
|
|
base_color->red / 255.0,
|
|
base_color->green / 255.0,
|
|
base_color->blue / 255.0,
|
|
base_color->alpha / 255.0);
|
|
cairo_pattern_add_color_stop_rgba (pattern,
|
|
0.9,
|
|
base_color->red / 255.0,
|
|
base_color->green / 255.0,
|
|
base_color->blue / 255.0,
|
|
0.1);
|
|
|
|
cairo_set_source (cr, pattern);
|
|
cairo_fill_preserve (cr);
|
|
|
|
cairo_pattern_destroy (pattern);
|
|
cairo_destroy (cr);
|
|
|
|
clutter_actor_set_name (retval, "bouncer");
|
|
clutter_actor_set_size (retval, width, height);
|
|
clutter_actor_set_anchor_point (retval, width / 2, height / 2);
|
|
clutter_actor_set_reactive (retval, TRUE);
|
|
|
|
return retval;
|
|
}
|
|
|
|
static GOptionEntry test_easing_entries[] = {
|
|
{
|
|
"re-center", 'r',
|
|
0,
|
|
G_OPTION_ARG_NONE, &recenter,
|
|
"Re-center the actor when the animation ends",
|
|
NULL
|
|
},
|
|
{
|
|
"duration", 'd',
|
|
0,
|
|
G_OPTION_ARG_INT, &duration,
|
|
"Duration of the animation",
|
|
"SECONDS"
|
|
},
|
|
|
|
{ NULL }
|
|
};
|
|
|
|
G_MODULE_EXPORT int
|
|
test_easing_main (int argc, char *argv[])
|
|
{
|
|
ClutterActor *stage, *rect, *label;
|
|
ClutterColor stage_color = { 0x88, 0x88, 0xdd, 0xff };
|
|
ClutterColor rect_color = { 0xee, 0x33, 0, 0xff };
|
|
gchar *text;
|
|
gfloat stage_width, stage_height;
|
|
gfloat label_width, label_height;
|
|
|
|
clutter_init_with_args (&argc, &argv,
|
|
NULL,
|
|
test_easing_entries,
|
|
NULL,
|
|
NULL);
|
|
|
|
stage = clutter_stage_get_default ();
|
|
clutter_stage_set_color (CLUTTER_STAGE (stage), &stage_color);
|
|
main_stage = stage;
|
|
|
|
clutter_actor_get_size (stage, &stage_width, &stage_height);
|
|
|
|
rect = make_bouncer (&rect_color, 50, 50);
|
|
clutter_container_add_actor (CLUTTER_CONTAINER (stage), rect);
|
|
clutter_actor_set_position (rect, stage_width / 2, stage_height / 2);
|
|
|
|
text = g_strdup_printf ("Easing mode: %s (%d of %d)\n"
|
|
"Right click to change the easing mode",
|
|
easing_modes[current_mode].name,
|
|
current_mode + 1,
|
|
n_easing_modes);
|
|
|
|
label = clutter_text_new ();
|
|
clutter_container_add_actor (CLUTTER_CONTAINER (stage), label);
|
|
clutter_text_set_font_name (CLUTTER_TEXT (label), "Sans 18px");
|
|
clutter_text_set_text (CLUTTER_TEXT (label), text);
|
|
clutter_actor_get_size (label, &label_width, &label_height);
|
|
clutter_actor_set_position (label,
|
|
stage_width - label_width - 10,
|
|
stage_height - label_height - 10);
|
|
easing_mode_label = label;
|
|
|
|
g_free (text);
|
|
|
|
g_signal_connect (stage,
|
|
"button-press-event", G_CALLBACK (on_button_press),
|
|
rect);
|
|
|
|
clutter_actor_show (stage);
|
|
|
|
clutter_main ();
|
|
|
|
return EXIT_SUCCESS;
|
|
}
|