From c27b00d7ef4caeb5f30cdefe564a3b8a83b49750 Mon Sep 17 00:00:00 2001 From: Matthew Allum Date: Wed, 25 Jul 2007 12:17:44 +0000 Subject: [PATCH] 2007-07-25 Matthew Allum * clutter/clutter-behaviour-rotate.c: * clutter/clutter-behaviour-rotate.h: Split 'center' prop into 3 seperate props for each axis. Use clutter_behaviour_actors_foreach() rather than clutter_behaviour_get_actors() to avoid copying list. Call fixed point rotation funcs internally. * clutter/clutter-effect.c: * clutter/clutter-effect.h: Add new simple rotation based effect funcs. --- ChangeLog | 13 ++ clutter/clutter-behaviour-rotate.c | 197 ++++++++++++++++++++--------- clutter/clutter-behaviour-rotate.h | 9 +- clutter/clutter-effect.c | 188 +++++++++++++++++++++++++++ clutter/clutter-effect.h | 30 +++++ 5 files changed, 377 insertions(+), 60 deletions(-) diff --git a/ChangeLog b/ChangeLog index a815b7e2c..9e40ee911 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,16 @@ +2007-07-25 Matthew Allum + + * clutter/clutter-behaviour-rotate.c: + * clutter/clutter-behaviour-rotate.h: + Split 'center' prop into 3 seperate props for each axis. + Use clutter_behaviour_actors_foreach() rather than + clutter_behaviour_get_actors() to avoid copying list. + Call fixed point rotation funcs internally. + + * clutter/clutter-effect.c: + * clutter/clutter-effect.h: + Add new simple rotation based effect funcs. + 2007-07-25 Emmanuele Bassi * clutter/clutter.h: Include clutter-behaviour-depth.h diff --git a/clutter/clutter-behaviour-rotate.c b/clutter/clutter-behaviour-rotate.c index 86f57b50a..92f53ea2e 100644 --- a/clutter/clutter-behaviour-rotate.c +++ b/clutter/clutter-behaviour-rotate.c @@ -59,7 +59,7 @@ struct _ClutterBehaviourRotatePrivate ClutterRotateAxis axis; ClutterRotateDirection direction; - ClutterKnot center; + gint center_x, center_y, center_z; }; #define CLUTTER_BEHAVIOUR_ROTATE_GET_PRIVATE(obj) \ @@ -75,9 +75,45 @@ enum PROP_ANGLE_END, PROP_AXIS, PROP_DIRECTION, - PROP_CENTER + PROP_CENTER_X, + PROP_CENTER_Y, + PROP_CENTER_Z }; +static void +alpha_notify_foreach (ClutterBehaviour *behaviour, + ClutterActor *actor, + gpointer data) +{ + ClutterFixed angle; + ClutterBehaviourRotate *rotate_behaviour; + ClutterBehaviourRotatePrivate *priv; + + rotate_behaviour = CLUTTER_BEHAVIOUR_ROTATE (behaviour); + priv = rotate_behaviour->priv; + + angle = GPOINTER_TO_UINT(data); + + switch (priv->axis) + { + case CLUTTER_X_AXIS: + clutter_actor_rotate_xx (actor, + angle, + priv->center_y, priv->center_z); + break; + case CLUTTER_Y_AXIS: + clutter_actor_rotate_yx (actor, + angle, + priv->center_x, priv->center_z); + break; + case CLUTTER_Z_AXIS: + clutter_actor_rotate_zx (actor, + angle, + priv->center_x, priv->center_y); + break; + } +} + static void clutter_behaviour_rotate_alpha_notify (ClutterBehaviour *behaviour, guint32 alpha_value) @@ -85,7 +121,6 @@ clutter_behaviour_rotate_alpha_notify (ClutterBehaviour *behaviour, ClutterFixed factor, angle; ClutterBehaviourRotate *rotate_behaviour; ClutterBehaviourRotatePrivate *priv; - GSList *actors, *l; rotate_behaviour = CLUTTER_BEHAVIOUR_ROTATE (behaviour); priv = rotate_behaviour->priv; @@ -105,31 +140,9 @@ clutter_behaviour_rotate_alpha_notify (ClutterBehaviour *behaviour, break; } - actors = clutter_behaviour_get_actors (behaviour); - for (l = actors; l; l = l->next) - { - ClutterActor *actor = l->data; - - switch (priv->axis) - { - case CLUTTER_X_AXIS: - clutter_actor_rotate_x (actor, - CLUTTER_FIXED_TO_FLOAT (angle), - priv->center.x, priv->center.y); - break; - case CLUTTER_Y_AXIS: - clutter_actor_rotate_y (actor, - CLUTTER_FIXED_TO_FLOAT (angle), - priv->center.x, priv->center.y); - break; - case CLUTTER_Z_AXIS: - clutter_actor_rotate_z (actor, - CLUTTER_FIXED_TO_FLOAT (angle), - priv->center.x, priv->center.y); - break; - } - } - g_slist_free (actors); + clutter_behaviour_actors_foreach (behaviour, + alpha_notify_foreach, + GUINT_TO_POINTER ((guint)angle)); } static void @@ -158,12 +171,23 @@ clutter_behaviour_rotate_set_property (GObject *gobject, case PROP_DIRECTION: priv->direction = g_value_get_enum (value); break; - case PROP_CENTER: - { - ClutterKnot *knot = g_value_get_boxed (value); - if (knot) - clutter_behaviour_rotate_set_center (rotate, knot); - } + case PROP_CENTER_X: + clutter_behaviour_rotate_set_center (rotate, + g_value_get_int (value), + priv->center_y, + priv->center_z); + break; + case PROP_CENTER_Y: + clutter_behaviour_rotate_set_center (rotate, + priv->center_x, + g_value_get_int (value), + priv->center_z); + break; + case PROP_CENTER_Z: + clutter_behaviour_rotate_set_center (rotate, + priv->center_x, + priv->center_y, + g_value_get_int (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); @@ -195,8 +219,14 @@ clutter_behaviour_rotate_get_property (GObject *gobject, case PROP_DIRECTION: g_value_set_enum (value, priv->direction); break; - case PROP_CENTER: - g_value_set_boxed (value, &priv->center); + case PROP_CENTER_X: + g_value_set_int (value, priv->center_x); + break; + case PROP_CENTER_Y: + g_value_set_int (value, priv->center_y); + break; + case PROP_CENTER_Z: + g_value_set_int (value, priv->center_z); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); @@ -274,20 +304,51 @@ clutter_behaviour_rotate_class_init (ClutterBehaviourRotateClass *klass) CLUTTER_ROTATE_CW, CLUTTER_PARAM_READWRITE)); /** - * ClutterBehaviourRotate:center: + * ClutterBehaviourRotate:center-x: * - * The center of rotation. The coordinates are relative to the plane normal - * to the axis of rotation. + * The x center of rotation. * * Since: 0.4 */ g_object_class_install_property (gobject_class, - PROP_CENTER, - g_param_spec_boxed ("center", - "Center", - "Center of rotation", - CLUTTER_TYPE_KNOT, - CLUTTER_PARAM_READWRITE)); + PROP_CENTER_X, + g_param_spec_int ("center-x", + "Center-X", + "X center of rotation", + -G_MAXINT, G_MAXINT, + 0, + CLUTTER_PARAM_READWRITE)); + + /** + * ClutterBehaviourRotate:center-y: + * + * The y center of rotation. + * + * Since: 0.4 + */ + g_object_class_install_property (gobject_class, + PROP_CENTER_Y, + g_param_spec_int ("center-y", + "Center-Y", + "Y center of rotation", + -G_MAXINT, G_MAXINT, + 0, + CLUTTER_PARAM_READWRITE)); + /** + * ClutterBehaviourRotate:center-z: + * + * The z center of rotation. + * + * Since: 0.4 + */ + g_object_class_install_property (gobject_class, + PROP_CENTER_Z, + g_param_spec_int ("center-z", + "Center-Z", + "Z center of rotation", + -G_MAXINT, G_MAXINT, + 0, + CLUTTER_PARAM_READWRITE)); g_type_class_add_private (klass, sizeof (ClutterBehaviourRotatePrivate)); } @@ -303,7 +364,7 @@ clutter_behaviour_rotate_init (ClutterBehaviourRotate *rotate) priv->angle_end = CLUTTER_FLOAT_TO_FIXED (360.0); priv->axis = CLUTTER_Z_AXIS; priv->direction = CLUTTER_ROTATE_CW; - priv->center.x = priv->center.y = 0; + priv->center_x = priv->center_y = priv->center_z = 0; } /** @@ -573,7 +634,9 @@ clutter_behaviour_rotate_set_boundsx (ClutterBehaviourRotate *rotate, /** * clutter_behaviour_rotate_set_center: * @rotate: a #ClutterBehaviourRotate - * @center: a #ClutterKnot + * @x: X axis center of rotation + * @y: Y axis center of rotation + * @z: Z axis center of rotation * * Sets the center of rotation. The coordinates are relative to the plane * normal to the rotation axis set with clutter_behaviour_rotate_set_axis(). @@ -582,28 +645,41 @@ clutter_behaviour_rotate_set_boundsx (ClutterBehaviourRotate *rotate, */ void clutter_behaviour_rotate_set_center (ClutterBehaviourRotate *rotate, - const ClutterKnot *center) + gint x, + gint y, + gint z) { ClutterBehaviourRotatePrivate *priv; g_return_if_fail (CLUTTER_IS_BEHAVIOUR_ROTATE (rotate)); - g_return_if_fail (center != NULL); priv = rotate->priv; - if (priv->center.x != center->x || priv->center.y != center->y) + if (priv->center_x != x) { - priv->center.x = center->x; - priv->center.y = center->y; + priv->center_x = x; + g_object_notify (G_OBJECT (rotate), "center-x"); + } - g_object_notify (G_OBJECT (rotate), "center"); + if (priv->center_y != y) + { + priv->center_y = y; + g_object_notify (G_OBJECT (rotate), "center-y"); + } + + if (priv->center_z != z) + { + priv->center_z = z; + g_object_notify (G_OBJECT (rotate), "center-z"); } } /** * clutter_behaviour_rotate_get_center: * @rotate: a #ClutterBehaviourRotate - * @center: return location for the center of rotation + * @x: return location for the X center of rotation + * @y: return location for the Y center of rotation + * @z: return location for the Z center of rotation * * Retrieves the center of rotation set using * clutter_behaviour_rotate_set_center(). @@ -612,15 +688,20 @@ clutter_behaviour_rotate_set_center (ClutterBehaviourRotate *rotate, */ void clutter_behaviour_rotate_get_center (ClutterBehaviourRotate *rotate, - ClutterKnot *center) + gint *x, + gint *y, + gint *z) { ClutterBehaviourRotatePrivate *priv; g_return_if_fail (CLUTTER_IS_BEHAVIOUR_ROTATE (rotate)); - g_return_if_fail (center != NULL); priv = rotate->priv; - center->x = priv->center.x; - center->y = priv->center.y; + if (x) + *x = priv->center_x; + if (y) + *y = priv->center_y; + if (z) + *z = priv->center_x; } diff --git a/clutter/clutter-behaviour-rotate.h b/clutter/clutter-behaviour-rotate.h index 8afedfcf4..17a0fbe96 100644 --- a/clutter/clutter-behaviour-rotate.h +++ b/clutter/clutter-behaviour-rotate.h @@ -80,9 +80,14 @@ ClutterBehaviour *clutter_behaviour_rotate_newx (ClutterAlpha *alpha, ClutterFixed angle_end); void clutter_behaviour_rotate_get_center (ClutterBehaviourRotate *rotate, - ClutterKnot *center); + gint *x, + gint *y, + gint *z); void clutter_behaviour_rotate_set_center (ClutterBehaviourRotate *rotate, - const ClutterKnot *knot); + gint x, + gint y, + gint z); + ClutterRotateAxis clutter_behaviour_rotate_get_axis (ClutterBehaviourRotate *rotate); void clutter_behaviour_rotate_set_axis (ClutterBehaviourRotate *rotate, ClutterRotateAxis axis); diff --git a/clutter/clutter-effect.c b/clutter/clutter-effect.c index 9577573bf..61033ca51 100644 --- a/clutter/clutter-effect.c +++ b/clutter/clutter-effect.c @@ -427,6 +427,8 @@ clutter_effect_fade (ClutterEffectTemplate *template_, c->completed_func = completed_func; c->completed_data = completed_data; + clutter_actor_set_opacity (actor, start_opacity); + c->behave = clutter_behaviour_opacity_new (c->alpha, start_opacity, end_opacity); @@ -472,6 +474,9 @@ clutter_effect_move (ClutterEffectTemplate *template_, c->completed_func = completed_func; c->completed_data = completed_data; + if (n_knots) + clutter_actor_set_position (actor, knots[0].x, knots[0].y); + c->behave = clutter_behaviour_path_new (c->alpha, knots, n_knots); clutter_behaviour_apply (c->behave, actor); @@ -517,6 +522,9 @@ clutter_effect_scale (ClutterEffectTemplate *template_, c->completed_func = completed_func; c->completed_data = completed_data; + clutter_actor_set_scale_with_gravity (actor, + scale_begin, scale_begin, gravity); + c->behave = clutter_behaviour_scale_new (c->alpha, scale_begin, scale_end, @@ -527,3 +535,183 @@ clutter_effect_scale (ClutterEffectTemplate *template_, return c->timeline; } + +/** + * clutter_effect_rotate_x: + * @template_: A #ClutterEffectTemplate + * @actor: A #ClutterActor to apply the effect to. + * @angle_begin: 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 + * + * 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_x (ClutterEffectTemplate *template_, + ClutterActor *actor, + gdouble angle_begin, + gdouble angle_end, + gint center_y, + 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_rotate_x (actor, angle_begin, center_y, center_y); + + c->behave = clutter_behaviour_rotate_new (c->alpha, + CLUTTER_X_AXIS, + direction, + angle_begin, + angle_end); + g_object_set (c->behave, + "center-y", center_y, + "center-z", center_z, + NULL); + + clutter_behaviour_apply (c->behave, actor); + clutter_timeline_start (c->timeline); + + return c->timeline; +} + +/** + * clutter_effect_rotate_y: + * @template_: A #ClutterEffectTemplate + * @actor: A #ClutterActor to apply the effect to. + * @angle_begin: 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_begin, + 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_rotate_y (actor, angle_begin, center_x, center_z); + + c->behave = clutter_behaviour_rotate_new (c->alpha, + CLUTTER_Y_AXIS, + direction, + angle_begin, + 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_y: + * @template_: A #ClutterEffectTemplate + * @actor: A #ClutterActor to apply the effect to. + * @angle_begin: 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_begin, + 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_rotate_z (actor, angle_begin, center_x, center_y); + + c->behave = clutter_behaviour_rotate_new (c->alpha, + CLUTTER_Z_AXIS, + direction, + angle_begin, + 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; +} diff --git a/clutter/clutter-effect.h b/clutter/clutter-effect.h index 9a7fb7bf4..6d0088a0a 100644 --- a/clutter/clutter-effect.h +++ b/clutter/clutter-effect.h @@ -117,6 +117,36 @@ ClutterTimeline *clutter_effect_scale (ClutterEffectTemplate *template_, ClutterEffectCompleteFunc completed_func, gpointer completed_data); +ClutterTimeline * clutter_effect_rotate_x (ClutterEffectTemplate *template_, + ClutterActor *actor, + gdouble angle_begin, + gdouble angle_end, + 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_begin, + 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_begin, + gdouble angle_end, + gint center_x, + gint center_y, + ClutterRotateDirection direction, + ClutterEffectCompleteFunc completed_func, + gpointer completed_data); + + G_END_DECLS #endif /* _CLUTTER_EFFECT */