2007-11-23 Emmanuele Bassi <ebassi@openedhand.com>

* clutter/clutter-effect.[ch]: Update the effects API to remove
	the start value for most of them.

	(clutter_effect_move): Make it a simple "move from current
	position to new coordinates" effect.

	(clutter_effect_path): Rename from clutter_effect_move().

	(clutter_effect_rotate): Sync up with the new actor rotation API.

	* tests/test-effects.c: Regression test for the effects.

	* tests/Makefile.am: Build glue for test-effects

	* tests/test-behave.c: Emulate a full ramp by using a looping
	timeline changing its direction when reaching the last frame.
This commit is contained in:
Emmanuele Bassi 2007-11-23 11:23:19 +00:00
parent e57b42ae52
commit 2b447c3b48
6 changed files with 308 additions and 270 deletions

View File

@ -1,3 +1,22 @@
2007-11-23 Emmanuele Bassi <ebassi@openedhand.com>
* clutter/clutter-effect.[ch]: Update the effects API to remove
the start value for most of them.
(clutter_effect_move): Make it a simple "move from current
position to new coordinates" effect.
(clutter_effect_path): Rename from clutter_effect_move().
(clutter_effect_rotate): Sync up with the new actor rotation API.
* tests/test-effects.c: Regression test for the effects.
* tests/Makefile.am: Build glue for test-effects
* tests/test-behave.c: Emulate a full ramp by using a looping
timeline changing its direction when reaching the last frame.
2007-11-23 Emmanuele Bassi <ebassi@openedhand.com>
* clutter/clutter-actor.c (clutter_actor_destroy): Bail out

View File

@ -517,11 +517,10 @@ on_effect_complete (ClutterTimeline *timeline,
* clutter_effect_fade:
* @template_: A #ClutterEffectTemplate
* @actor: A #ClutterActor to apply the effect to.
* @opacity_start: Initial opacity value to apply to actor
* @opacity_end: Final opacity value to apply to actor
* @completed_func: A #ClutterEffectCompleteFunc to call on effect
* @func: A #ClutterEffectCompleteFunc to call on effect
* completion or %NULL
* @completed_data: Data to pass to supplied #ClutterEffectCompleteFunc
* @data: Data to pass to supplied #ClutterEffectCompleteFunc
* or %NULL
*
* Simple effect for fading a single #ClutterActor.
@ -529,26 +528,26 @@ on_effect_complete (ClutterTimeline *timeline,
* Return value: a #ClutterTimeline for the effect. Will be unrefed by
* the effect when completed.
*
* Since: 0.4
* Since: 0.6
*/
ClutterTimeline *
clutter_effect_fade (ClutterEffectTemplate *template_,
ClutterActor *actor,
guint8 opacity_start,
guint8 opacity_end,
ClutterEffectCompleteFunc completed_func,
gpointer completed_data)
ClutterEffectCompleteFunc func,
gpointer data)
{
ClutterEffectClosure *c;
guint8 opacity_start;
c = clutter_effect_closure_new (template_,
actor,
G_CALLBACK (on_effect_complete));
c->completed_func = completed_func;
c->completed_data = completed_data;
c->completed_func = func;
c->completed_data = data;
clutter_actor_set_opacity (actor, opacity_start);
opacity_start = clutter_actor_get_opacity (actor);
c->behave = clutter_behaviour_opacity_new (c->alpha,
opacity_start,
@ -564,11 +563,10 @@ clutter_effect_fade (ClutterEffectTemplate *template_,
* clutter_effect_depth:
* @template_: A #ClutterEffectTemplate
* @actor: A #ClutterActor to apply the effect to.
* @depth_start: Initial depth value to apply to actor
* @depth_end: Final depth value to apply to actor
* @completed_func: A #ClutterEffectCompleteFunc to call on effect
* @func: A #ClutterEffectCompleteFunc to call on effect
* completion or %NULL
* @completed_data: Data to pass to supplied #ClutterEffectCompleteFunc
* @data: Data to pass to supplied #ClutterEffectCompleteFunc
* or %NULL
*
* Simple effect for changing the depth of a single #ClutterActor.
@ -576,24 +574,26 @@ clutter_effect_fade (ClutterEffectTemplate *template_,
* Return value: a #ClutterTimeline for the effect. Will be unrefed by
* the effect when completed.
*
* Since: 0.4
* Since: 0.6
*/
ClutterTimeline *
clutter_effect_depth (ClutterEffectTemplate *template_,
ClutterActor *actor,
gint depth_start,
gint depth_end,
ClutterEffectCompleteFunc completed_func,
gpointer completed_data)
ClutterEffectCompleteFunc func,
gpointer data)
{
ClutterEffectClosure *c;
gint depth_start;
c = clutter_effect_closure_new (template_,
actor,
G_CALLBACK (on_effect_complete));
c->completed_func = completed_func;
c->completed_data = completed_data;
c->completed_func = func;
c->completed_data = data;
depth_start = clutter_actor_get_depth (actor);
c->behave = clutter_behaviour_depth_new (c->alpha, depth_start, depth_end);
@ -607,11 +607,61 @@ clutter_effect_depth (ClutterEffectTemplate *template_,
* clutter_effect_move:
* @template_: A #ClutterEffectTemplate
* @actor: A #ClutterActor to apply the effect to.
* @x: X coordinate of the destination
* @y: Y coordinate of the destination
* @func: A #ClutterEffectCompleteFunc to call on effect
* completion or %NULL
* @data: Data to pass to supplied #ClutterEffectCompleteFunc
* or %NULL
*
* Simple effect for moving a single #ClutterActor along to a
* destination point.
*
* Return value: a #ClutterTimeline for the effect. Will be unreferenced by
* the effect when completed.
*
* Since: 0.6
*/
ClutterTimeline *
clutter_effect_move (ClutterEffectTemplate *template_,
ClutterActor *actor,
gint x,
gint y,
ClutterEffectCompleteFunc func,
gpointer data)
{
ClutterEffectClosure *c;
ClutterKnot knots[2];
c = clutter_effect_closure_new (template_,
actor,
G_CALLBACK (on_effect_complete));
c->completed_func = func;
c->completed_data = data;
knots[0].x = clutter_actor_get_x (actor);
knots[0].y = clutter_actor_get_y (actor);
knots[1].x = x;
knots[1].y = y;
c->behave = clutter_behaviour_path_new (c->alpha, knots, 2);
clutter_behaviour_apply (c->behave, actor);
clutter_timeline_start (c->timeline);
return c->timeline;
}
/**
* clutter_effect_path:
* @template_: A #ClutterEffectTemplate
* @actor: A #ClutterActor to apply the effect to.
* @knots: An array of #ClutterKnots representing path for the actor
* @n_knots: Number of #ClutterKnots in passed array.
* @completed_func: A #ClutterEffectCompleteFunc to call on effect
* @func: A #ClutterEffectCompleteFunc to call on effect
* completion or %NULL
* @completed_data: Data to pass to supplied #ClutterEffectCompleteFunc
* @data: Data to pass to supplied #ClutterEffectCompleteFunc
* or %NULL
*
* Simple effect for moving a single #ClutterActor along a path.
@ -619,15 +669,15 @@ clutter_effect_depth (ClutterEffectTemplate *template_,
* Return value: a #ClutterTimeline for the effect. Will be unreferenced by
* the effect when completed.
*
* Since: 0.4
* Since: 0.6
*/
ClutterTimeline *
clutter_effect_move (ClutterEffectTemplate *template_,
clutter_effect_path (ClutterEffectTemplate *template_,
ClutterActor *actor,
const ClutterKnot *knots,
guint n_knots,
ClutterEffectCompleteFunc completed_func,
gpointer completed_data)
ClutterEffectCompleteFunc func,
gpointer data)
{
ClutterEffectClosure *c;
@ -635,8 +685,8 @@ clutter_effect_move (ClutterEffectTemplate *template_,
actor,
G_CALLBACK (on_effect_complete));
c->completed_func = completed_func;
c->completed_data = completed_data;
c->completed_func = func;
c->completed_data = data;
if (n_knots)
clutter_actor_set_position (actor, knots[0].x, knots[0].y);
@ -653,12 +703,11 @@ clutter_effect_move (ClutterEffectTemplate *template_,
* clutter_effect_scale:
* @template_: A #ClutterEffectTemplate
* @actor: A #ClutterActor to apply the effect to.
* @scale_start: Initial scale factor to apply to actor
* @scale_end: Final scale factor to apply to actor
* @gravity: A #ClutterGravity for the scale.
* @completed_func: A #ClutterEffectCompleteFunc to call on effect
* @func: A #ClutterEffectCompleteFunc to call on effect
* completion or NULL
* @completed_data: Data to pass to supplied #ClutterEffectCompleteFunc
* @data: Data to pass to supplied #ClutterEffectCompleteFunc
* or NULL
*
* Simple effect for scaling a single #ClutterActor.
@ -666,29 +715,27 @@ clutter_effect_move (ClutterEffectTemplate *template_,
* Return value: a #ClutterTimeline for the effect. Will be unreferenced by
* the effect when completed.
*
* Since: 0.4
* Since: 0.6
*/
ClutterTimeline *
clutter_effect_scale (ClutterEffectTemplate *template_,
ClutterActor *actor,
gdouble scale_start,
gdouble scale_end,
ClutterGravity gravity,
ClutterEffectCompleteFunc completed_func,
gpointer completed_data)
ClutterEffectCompleteFunc func,
gpointer data)
{
ClutterEffectClosure *c;
gdouble scale_start;
c = clutter_effect_closure_new (template_,
actor,
G_CALLBACK (on_effect_complete));
c->completed_func = completed_func;
c->completed_data = completed_data;
clutter_actor_set_scale_with_gravity (actor,
scale_start, scale_start, gravity);
c->completed_func = func;
c->completed_data = data;
clutter_actor_get_scale (actor, &scale_start, NULL);
c->behave = clutter_behaviour_scale_new (c->alpha,
scale_start,
scale_end,
@ -701,50 +748,49 @@ clutter_effect_scale (ClutterEffectTemplate *template_,
}
/**
* clutter_effect_rotate_x:
* @template_: A #ClutterEffectTemplate
* @actor: A #ClutterActor to apply the effect to.
* @angle_start: Initial angle to apply to actor
* @angle_end: Final angle to apply to actor
* @center_y: Position on Y axis to rotate about.
* @center_z: Position on Z axis to rotate about.
* @direction: A #ClutterRotateDirection for the rotation.
* @completed_func: A #ClutterEffectCompleteFunc to call on effect
* completion or NULL
* @completed_data: Data to pass to supplied #ClutterEffectCompleteFunc
* or NULL
* clutter_effect_rotate:
* @template_: a #ClutterEffectTemplate
* @actor: a #ClutterActor to apply the effect to.
* @axis: axis of rotation
* @angle: final angle to apply to actor
* @center_z: position on Z axis to rotate about.
* @center_y: position on Y axis to rotate about.
* @center_z: position on Z axis to rotate about.
* @direction: a #ClutterRotateDirection for the rotation.
* @func: a #ClutterEffectCompleteFunc to call on effect
* completion or %NULL
* @data: user data to pass to supplied @func or %NULL
*
* Simple effect for rotating a single #ClutterActor about x axis.
* Simple effect for rotating a single #ClutterActor.
*
* Return value: a #ClutterTimeline for the effect. Will be unreferenced by
* the effect when completed.
*
* Since: 0.4
* Since: 0.6
*/
ClutterTimeline *
clutter_effect_rotate_x (ClutterEffectTemplate *template_,
clutter_effect_rotate (ClutterEffectTemplate *template_,
ClutterActor *actor,
gdouble angle_start,
ClutterRotateAxis axis,
gdouble angle_end,
gint center_x,
gint center_y,
gint center_z,
ClutterRotateDirection direction,
ClutterEffectCompleteFunc completed_func,
gpointer completed_data)
ClutterEffectCompleteFunc func,
gpointer data)
{
ClutterEffectClosure *c;
gdouble angle_start;
c = clutter_effect_closure_new (template_,
actor,
G_CALLBACK (on_effect_complete));
c->completed_func = completed_func;
c->completed_data = completed_data;
c->completed_func = func;
c->completed_data = data;
clutter_actor_set_rotation (actor, CLUTTER_X_AXIS,
angle_start,
0, center_y, center_z);
angle_start = clutter_actor_get_rotation (actor, axis, NULL, NULL, NULL);
c->behave = clutter_behaviour_rotate_new (c->alpha,
CLUTTER_X_AXIS,
@ -752,6 +798,7 @@ clutter_effect_rotate_x (ClutterEffectTemplate *template_,
angle_start,
angle_end);
g_object_set (c->behave,
"center-x", center_x,
"center-y", center_y,
"center-z", center_z,
NULL);
@ -761,127 +808,3 @@ clutter_effect_rotate_x (ClutterEffectTemplate *template_,
return c->timeline;
}
/**
* clutter_effect_rotate_y:
* @template_: A #ClutterEffectTemplate
* @actor: A #ClutterActor to apply the effect to.
* @angle_start: Initial angle to apply to actor
* @angle_end: Final angle to apply to actor
* @center_x: Position on X axis to rotate about.
* @center_z: Position on Z axis to rotate about.
* @direction: A #ClutterRotateDirection for the rotation.
* @completed_func: A #ClutterEffectCompleteFunc to call on effect
* completion or NULL
* @completed_data: Data to pass to supplied #ClutterEffectCompleteFunc
* or NULL
*
* Simple effect for rotating a single #ClutterActor about y axis.
*
* Return value: a #ClutterTimeline for the effect. Will be unreferenced by
* the effect when completed.
*
* Since: 0.4
*/
ClutterTimeline *
clutter_effect_rotate_y (ClutterEffectTemplate *template_,
ClutterActor *actor,
gdouble angle_start,
gdouble angle_end,
gint center_x,
gint center_z,
ClutterRotateDirection direction,
ClutterEffectCompleteFunc completed_func,
gpointer completed_data)
{
ClutterEffectClosure *c;
c = clutter_effect_closure_new (template_,
actor,
G_CALLBACK (on_effect_complete));
c->completed_func = completed_func;
c->completed_data = completed_data;
clutter_actor_set_rotation (actor, CLUTTER_Y_AXIS,
angle_start,
center_x, 0, center_z);
c->behave = clutter_behaviour_rotate_new (c->alpha,
CLUTTER_Y_AXIS,
direction,
angle_start,
angle_end);
g_object_set (c->behave,
"center-x", center_x,
"center-z", center_z,
NULL);
clutter_behaviour_apply (c->behave, actor);
clutter_timeline_start (c->timeline);
return c->timeline;
}
/**
* clutter_effect_rotate_z:
* @template_: A #ClutterEffectTemplate
* @actor: A #ClutterActor to apply the effect to.
* @angle_start: Initial angle to apply to actor
* @angle_end: Final angle to apply to actor
* @center_x: Position on X axis to rotate about.
* @center_y: Position on Y axis to rotate about.
* @direction: A #ClutterRotateDirection for the rotation.
* @completed_func: A #ClutterEffectCompleteFunc to call on effect
* completion or NULL
* @completed_data: Data to pass to supplied #ClutterEffectCompleteFunc
* or NULL
*
* Simple effect for rotating a single #ClutterActor about z axis.
*
* Return value: a #ClutterTimeline for the effect. Will be unreferenced by
* the effect when completed.
*
* Since: 0.4
*/
ClutterTimeline *
clutter_effect_rotate_z (ClutterEffectTemplate *template_,
ClutterActor *actor,
gdouble angle_start,
gdouble angle_end,
gint center_x,
gint center_y,
ClutterRotateDirection direction,
ClutterEffectCompleteFunc completed_func,
gpointer completed_data)
{
ClutterEffectClosure *c;
c = clutter_effect_closure_new (template_,
actor,
G_CALLBACK (on_effect_complete));
c->completed_func = completed_func;
c->completed_data = completed_data;
clutter_actor_set_rotation (actor, CLUTTER_Z_AXIS,
angle_start,
center_x, center_y, 0);
c->behave = clutter_behaviour_rotate_new (c->alpha,
CLUTTER_Z_AXIS,
direction,
angle_start,
angle_end);
g_object_set (c->behave,
"center-x", center_x,
"center-y", center_y,
NULL);
clutter_behaviour_apply (c->behave, actor);
clutter_timeline_start (c->timeline);
return c->timeline;
}

View File

@ -113,58 +113,42 @@ gboolean clutter_effect_template_get_timeline_clone (ClutterEffect
ClutterTimeline *clutter_effect_fade (ClutterEffectTemplate *template_,
ClutterActor *actor,
guint8 opacity_start,
guint8 opacity_end,
ClutterEffectCompleteFunc completed_func,
gpointer completed_data);
ClutterEffectCompleteFunc func,
gpointer data);
ClutterTimeline *clutter_effect_depth (ClutterEffectTemplate *template_,
ClutterActor *actor,
gint depth_start,
gint depth_end,
ClutterEffectCompleteFunc completed_func,
gpointer completed_data);
ClutterEffectCompleteFunc func,
gpointer data);
ClutterTimeline *clutter_effect_move (ClutterEffectTemplate *template_,
ClutterActor *actor,
gint x,
gint y,
ClutterEffectCompleteFunc func,
gpointer data);
ClutterTimeline *clutter_effect_path (ClutterEffectTemplate *template_,
ClutterActor *actor,
const ClutterKnot *knots,
guint n_knots,
ClutterEffectCompleteFunc completed_func,
gpointer completed_data);
ClutterEffectCompleteFunc func,
gpointer data);
ClutterTimeline *clutter_effect_scale (ClutterEffectTemplate *template_,
ClutterActor *actor,
gdouble scale_start,
gdouble scale_end,
ClutterGravity gravity,
ClutterEffectCompleteFunc completed_func,
gpointer completed_data);
ClutterTimeline *clutter_effect_rotate_x (ClutterEffectTemplate *template_,
ClutterEffectCompleteFunc func,
gpointer data);
ClutterTimeline *clutter_effect_rotate (ClutterEffectTemplate *template_,
ClutterActor *actor,
gdouble angle_start,
gdouble angle_end,
ClutterRotateAxis axis,
gdouble angle,
gint center_x,
gint center_y,
gint center_z,
ClutterRotateDirection direction,
ClutterEffectCompleteFunc completed_func,
gpointer completed_data);
ClutterTimeline *clutter_effect_rotate_y (ClutterEffectTemplate *template_,
ClutterActor *actor,
gdouble angle_start,
gdouble angle_end,
gint center_x,
gint center_z,
ClutterRotateDirection direction,
ClutterEffectCompleteFunc completed_func,
gpointer completed_data);
ClutterTimeline *clutter_effect_rotate_z (ClutterEffectTemplate *template_,
ClutterActor *actor,
gdouble angle_start,
gdouble angle_end,
gint center_x,
gint center_y,
ClutterRotateDirection direction,
ClutterEffectCompleteFunc completed_func,
gpointer completed_data);
ClutterEffectCompleteFunc func,
gpointer data);
G_END_DECLS

View File

@ -1,7 +1,8 @@
noinst_PROGRAMS = test-textures test-events test-offscreen test-scale \
test-actors test-behave test-text test-entry test-project \
test-boxes test-perspective test-rotate test-depth \
test-threads test-timeline test-score test-script test-model test-grab
test-threads test-timeline test-score test-script \
test-model test-grab test-effects
INCLUDES = -I$(top_srcdir)/
LDADD = $(top_builddir)/clutter/libclutter-@CLUTTER_FLAVOUR@-@CLUTTER_MAJORMINOR@.la
@ -27,5 +28,6 @@ test_timeline_SOURCES = test-timeline.c
test_score_SOURCES = test-score.c
test_script_SOURCES = test-script.c
test_model_SOURCES = test-model.c
test_effects_SOURCES = test-effects.c
EXTRA_DIST = redhand.png test-script.json

View File

@ -43,6 +43,21 @@ scroll_event_cb (ClutterStage *stage,
return FALSE;
}
static void
timeline_completed (ClutterTimeline *timeline)
{
ClutterTimelineDirection direction;
direction = clutter_timeline_get_direction (timeline);
if (direction == CLUTTER_TIMELINE_FORWARD)
direction = CLUTTER_TIMELINE_BACKWARD;
else
direction = CLUTTER_TIMELINE_FORWARD;
clutter_timeline_set_direction (timeline, direction);
}
typedef enum {
PATH_POLY,
PATH_ELLIPSE,
@ -152,8 +167,11 @@ main (int argc, char *argv[])
clutter_container_add (CLUTTER_CONTAINER (group), rect, hand, NULL);
/* Make a timeline */
timeline = clutter_timeline_new (100, 26); /* num frames, fps */
g_object_set (timeline, "loop", TRUE, NULL);
timeline = clutter_timeline_new_for_duration (4000); /* num frames, fps */
clutter_timeline_set_loop (timeline, TRUE);
g_signal_connect (timeline,
"completed", G_CALLBACK (timeline_completed),
NULL);
/* Set an alpha func to power behaviour - ramp is constant rise/fall */
alpha = clutter_alpha_new_full (timeline,

92
tests/test-effects.c Normal file
View File

@ -0,0 +1,92 @@
#include <stdlib.h>
#include <clutter/clutter.h>
static ClutterEffectTemplate *tmpl = NULL;
static ClutterTimeline *timeline = NULL;
int
main (int argc, char *argv[])
{
ClutterActor *stage, *actor;
ClutterContainer *container;
ClutterColor stage_color = { 0xcc, 0xcc, 0xcc, 0xff };
ClutterColor rect_color = { 0, 0, 0, 0xdd };
clutter_init (&argc, &argv);
timeline = clutter_timeline_new_for_duration (5000);
clutter_timeline_set_loop (timeline, TRUE);
tmpl =
clutter_effect_template_new (timeline, CLUTTER_ALPHA_RAMP_INC);
stage = clutter_stage_get_default ();
container = CLUTTER_CONTAINER (stage);
g_signal_connect (stage,
"button-press-event", G_CALLBACK (clutter_main_quit),
NULL);
clutter_stage_set_color (CLUTTER_STAGE (stage), &stage_color);
clutter_stage_set_use_fog (CLUTTER_STAGE (stage), TRUE);
clutter_actor_set_size (stage, 800, 600);
clutter_actor_show_all (stage);
actor = clutter_rectangle_new_with_color (&rect_color);
clutter_container_add_actor (container, actor);
clutter_actor_set_size (actor, 50, 50);
clutter_actor_set_position (actor, 50, 10);
clutter_effect_fade (tmpl, actor, 0x22, NULL, NULL);
clutter_actor_show (actor);
actor = clutter_rectangle_new_with_color (&rect_color);
clutter_container_add_actor (container, actor);
clutter_actor_set_size (actor, 50, 50);
clutter_actor_set_position (actor, 750, 70);
clutter_effect_depth (tmpl, actor, -500, NULL, NULL);
clutter_actor_show (actor);
actor = clutter_rectangle_new_with_color (&rect_color);
clutter_container_add_actor (container, actor);
clutter_actor_set_size (actor, 50, 50);
clutter_actor_set_position (actor, 50, 140);
clutter_effect_move (tmpl, actor, 750, 140, NULL, NULL);
clutter_actor_show (actor);
actor = clutter_rectangle_new_with_color (&rect_color);
clutter_container_add_actor (container, actor);
clutter_actor_set_size (actor, 50, 50);
clutter_actor_set_position (actor, 750, 210);
{
ClutterKnot knots[2];
knots[0].x = 750; knots[0].y = 210;
knots[1].x = 350; knots[1].y = 210;
clutter_effect_path (tmpl, actor, knots, 2, NULL, NULL);
}
clutter_actor_show (actor);
actor = clutter_rectangle_new_with_color (&rect_color);
clutter_container_add_actor (container, actor);
clutter_actor_set_size (actor, 50, 50);
clutter_actor_set_position (actor, 50, 280);
clutter_effect_scale (tmpl, actor, 2.0, CLUTTER_GRAVITY_CENTER, NULL, NULL);
clutter_actor_show (actor);
actor = clutter_rectangle_new_with_color (&rect_color);
clutter_container_add_actor (container, actor);
clutter_actor_set_size (actor, 50, 50);
clutter_actor_set_position (actor, 750, 350);
clutter_effect_rotate (tmpl, actor,
CLUTTER_Z_AXIS, 180.0,
25, 25, 0,
CLUTTER_ROTATE_CW,
NULL, NULL);
clutter_actor_show (actor);
clutter_main ();
g_object_unref (tmpl);
g_object_unref (timeline);
return EXIT_SUCCESS;
}