diff --git a/ChangeLog b/ChangeLog index 7d003933a..f66d61bc1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2007-12-17 Tomas Frydrych + + * clutter/clutter-behaviour-ellipse.c: + * clutter/clutter-behaviour-rotate.c: + Clamping of start and end angles to <0, 360). + 2007-12-17 Emmanuele Bassi * clutter/clutter-behaviour-path.c: Clarify the equivalence @@ -53,7 +59,7 @@ ClutterModel vtable, to allow subclasses and language bindings to override the entire ClutterModel using other/native data types to store the rows. - + * clutter/clutter-model-default.[ch]: ClutterModelDefault is a default implementation of ClutterModel and ClutterModelIter using GSequence. @@ -110,7 +116,7 @@ (clutter_model_insert_value): Add a _value() variant for the insertion methods, for use of the language bindings. - (clutter_model_append), + (clutter_model_append), (clutter_model_prepend), (clutter_model_insert): Do not return a boolean: insertion should never fail unless for a programming error, in which case we have @@ -148,7 +154,7 @@ (clutter_geometry_get_type),(clutter_vertex_get_type), (clutter_actor_box_get_type): Use the I_() macro instead of directly calling g_intern_static_string(). - + * clutter/clutter-entry.c (clutter_entry_request_coords): * clutter/clutter-label.c (clutter_label_ensure_layout), (clutter_label_request_coords): Use CLUTTER_UNITS_FROM_DEVICE() diff --git a/clutter/clutter-behaviour-ellipse.c b/clutter/clutter-behaviour-ellipse.c index e8ab3e7b1..3dbb88647 100644 --- a/clutter/clutter-behaviour-ellipse.c +++ b/clutter/clutter-behaviour-ellipse.c @@ -183,74 +183,45 @@ actor_apply_knot_foreach (ClutterBehaviour *behave, clutter_actor_set_depth (actor, knot->z); } +static inline ClutterAngle +clamp_angle (ClutterAngle a) +{ + ClutterAngle a1, a2; + gint rounds; + + /* Need to add the 256 offset here, since the user space 0 maps to our + * -256 + */ + rounds = (a+256) / 1024; + a1 = rounds * 1024; + a2 = a - a1; + + return a2; +} + static void clutter_behaviour_ellipse_alpha_notify (ClutterBehaviour *behave, guint32 alpha) { ClutterBehaviourEllipse *self = CLUTTER_BEHAVIOUR_ELLIPSE (behave); ClutterBehaviourEllipsePrivate *priv = self->priv; + ClutterAngle start, end; knot3d knot; ClutterAngle angle = 0; - if ((priv->angle_end >= priv->angle_start && - priv->direction == CLUTTER_ROTATE_CW) || - (priv->angle_end < priv->angle_start && - priv->direction == CLUTTER_ROTATE_CCW)) + start = priv->angle_start; + end = priv->angle_end; + + if (priv->direction == CLUTTER_ROTATE_CW && start >= end) { - angle = (priv->angle_end - priv->angle_start) * alpha - / CLUTTER_ALPHA_MAX_ALPHA - + priv->angle_start; + end += 1024; } - else if (priv->angle_end >= priv->angle_start && - priv->direction == CLUTTER_ROTATE_CCW) + else if (priv->direction == CLUTTER_ROTATE_CCW && start <= end) { - ClutterAngle diff; - ClutterAngle angle_start = priv->angle_start + 256; - ClutterAngle angle_end = priv->angle_end + 256; - - /* Work out the angular length of the arch represented by the - * end angle in CCW direction - */ - if (angle_end >= 1024) - { - gint rounds = angle_end / 1024; - ClutterAngle a1 = rounds * 1024; - ClutterAngle a2 = - (angle_end - a1); - - diff = a1 + a2 + angle_start; - } - else - { - diff = 1024 - angle_end + angle_start; - } - - angle = priv->angle_start - (diff * alpha / CLUTTER_ALPHA_MAX_ALPHA); + end -= 1024; } - else if (priv->angle_end < priv->angle_start && - priv->direction == CLUTTER_ROTATE_CW) - { - ClutterAngle diff; - ClutterAngle angle_start = priv->angle_start + 256; - ClutterAngle angle_end = priv->angle_end + 256; - /* Work out the angular length of the arch represented by the - * start angle in CW direction - */ - if (angle_start >= 1024) - { - gint rounds = angle_start / 1024; - ClutterAngle a1 = rounds * 1024; - ClutterAngle a2 = - (angle_start - a1); - - diff = a1 + a2 + angle_end; - } - else - { - diff = 1024 - angle_start + angle_end; - } - - angle = priv->angle_start + (diff * alpha / CLUTTER_ALPHA_MAX_ALPHA); - } + angle = (end - start) * alpha / CLUTTER_ALPHA_MAX_ALPHA + start; clutter_behaviour_ellipse_advance (self, angle, &knot); @@ -409,7 +380,7 @@ clutter_behaviour_ellipse_class_init (ClutterBehaviourEllipseClass *klass) "Start Angle", "Initial angle", 0.0, - CLUTTER_ANGLE_MAX_DEG, + 360.0, 0.0, CLUTTER_PARAM_READWRITE)); /** @@ -425,8 +396,8 @@ clutter_behaviour_ellipse_class_init (ClutterBehaviourEllipseClass *klass) "End Angle", "Final angle", 0.0, - CLUTTER_ANGLE_MAX_DEG, 360.0, + 0.0, CLUTTER_PARAM_READWRITE)); /** * ClutterBehaviourEllipse:angle-tilt-x: @@ -539,6 +510,13 @@ clutter_behaviour_ellipse_init (ClutterBehaviourEllipse * self) self->priv = priv = CLUTTER_BEHAVIOUR_ELLIPSE_GET_PRIVATE (self); priv->direction = CLUTTER_ROTATE_CW; + + /* The inital values have to reflect the 90 degree offset between the normal + * mathematical space and the clutter clock-based space; the default end + * value of 360 is clamped to 0. + */ + priv->angle_start = -256; + priv->angle_end = -256; } /** @@ -549,12 +527,15 @@ clutter_behaviour_ellipse_init (ClutterBehaviourEllipse * self) * @width: width of the ellipse * @height: height of the ellipse * @direction: #ClutterRotateDirection of rotation - * @start: angle in degrees at which movement starts - * @end: angle in degrees at which movement ends + * @start: angle in degrees at which movement starts, between 0 and 360 + * @end: angle in degrees at which movement ends, between 0 and 360 * * Creates a behaviour that drives actors along an elliptical path with * given center, width and height; the movement starts at @angle_start - * degrees (with 0 corresponding to 12 o'clock) and ends at @angle_end degrees; + * degrees (with 0 corresponding to 12 o'clock) and ends at @angle_end + * degrees. Angles >= 360 degrees get clamped to the canonical interval + * <0, 360), if start == end, the behaviour will rotate by exacly 360 degrees. + * * Return value: the newly created #ClutterBehaviourEllipse * * Since: 0.4 @@ -786,9 +767,10 @@ clutter_behaviour_ellipse_get_height (ClutterBehaviourEllipse *self) /** * clutter_behaviour_ellipse_set_angle_start * @self: a #ClutterBehaviourEllipse - * @angle_start: angle at which movement starts in degrees + * @angle_start: angle at which movement starts in degrees, between 0 and 360. * - * Sets the angle at which movement starts. + * Sets the angle at which movement starts; angles >= 360 degress get clamped + * to the canonical interval <0, 360). * * Since: 0.6 */ @@ -805,9 +787,11 @@ clutter_behaviour_ellipse_set_angle_start (ClutterBehaviourEllipse *self, /** * clutter_behaviour_ellipse_set_angle_startx * @self: a #ClutterBehaviourEllipse - * @angle_start: An angle, as #ClutterFixed, at which movement starts, in degrees. + * @angle_start: An angle, as #ClutterFixed, at which movement starts, in + * degrees, between 0 and 360. * - * Sets the angle at which movement starts. + * Sets the angle at which movement starts; angles >= 360 degress get clamped + * to the canonical interval <0, 360). * * Since: 0.6 */ @@ -819,7 +803,7 @@ clutter_behaviour_ellipse_set_angle_startx (ClutterBehaviourEllipse *self, ClutterAngle new_angle; g_return_if_fail (CLUTTER_IS_BEHAVIOUR_ELLIPSE (self)); - new_angle = CLUTTER_ANGLE_FROM_DEGX (angle_start) - 256; + new_angle = clamp_angle (CLUTTER_ANGLE_FROM_DEGX (angle_start) - 256); priv = self->priv; if (priv->angle_start != new_angle) @@ -868,9 +852,10 @@ clutter_behaviour_ellipse_get_angle_startx (ClutterBehaviourEllipse *self) /** * clutter_behaviour_ellipse_set_angle_end * @self: a #ClutterBehaviourEllipse - * @angle_end: angle at which movement ends in degrees. + * @angle_end: angle at which movement ends in degrees, between 0 and 360. * - * Sets the angle at which movement ends. + * Sets the angle at which movement ends; angles >= 360 degress get clamped + * to the canonical interval <0, 360). * * Since: 0.4 */ @@ -887,9 +872,11 @@ clutter_behaviour_ellipse_set_angle_end (ClutterBehaviourEllipse *self, /** * clutter_behaviour_ellipse_set_angle_endx * @self: a #ClutterBehaviourEllipse - * @angle_end: angle, as #ClutterFixed, at which movement ends, in degrees. + * @angle_end: angle, as #ClutterFixed, at which movement ends, in degrees, + * between 0 and 360. * - * Sets the angle at which movement ends. + * Sets the angle at which movement ends; angles >= 360 degress get clamped + * to the canonical interval <0, 360). * * Since: 0.4 */ @@ -902,7 +889,7 @@ clutter_behaviour_ellipse_set_angle_endx (ClutterBehaviourEllipse *self, g_return_if_fail (CLUTTER_IS_BEHAVIOUR_ELLIPSE (self)); - new_angle = CLUTTER_ANGLE_FROM_DEGX (angle_end) - 256; + new_angle = clamp_angle (CLUTTER_ANGLE_FROM_DEGX (angle_end) - 256); priv = self->priv; diff --git a/clutter/clutter-behaviour-rotate.c b/clutter/clutter-behaviour-rotate.c index 4224780ec..e495f4018 100644 --- a/clutter/clutter-behaviour-rotate.c +++ b/clutter/clutter-behaviour-rotate.c @@ -83,7 +83,7 @@ enum PROP_CENTER_Z }; -static void +static void alpha_notify_foreach (ClutterBehaviour *behaviour, ClutterActor *actor, gpointer data) @@ -102,11 +102,24 @@ alpha_notify_foreach (ClutterBehaviour *behaviour, priv->center_z); } +static inline +ClutterFixed clamp_angle (ClutterFixed a) +{ + ClutterFixed a1, a2; + gint rounds; + + rounds = a / CFX_360; + a1 = rounds * CFX_360; + a2 = a - a1; + + return a2; +} + static void clutter_behaviour_rotate_alpha_notify (ClutterBehaviour *behaviour, guint32 alpha_value) { - ClutterFixed factor, angle, diff; + ClutterFixed factor, angle, start, end; ClutterBehaviourRotate *rotate_behaviour; ClutterBehaviourRotatePrivate *priv; @@ -115,74 +128,20 @@ clutter_behaviour_rotate_alpha_notify (ClutterBehaviour *behaviour, factor = CLUTTER_INT_TO_FIXED (alpha_value) / CLUTTER_ALPHA_MAX_ALPHA; angle = 0; - - switch (priv->direction) + + start = priv->angle_start; + end = priv->angle_end; + + if (priv->direction == CLUTTER_ROTATE_CW && start >= end) { - case CLUTTER_ROTATE_CW: - if (priv->angle_end >= priv->angle_start) - { - angle = CLUTTER_FIXED_MUL (factor, - (priv->angle_end - priv->angle_start)); - angle += priv->angle_start; - } - else - { - /* Work out the angular length of the arch represented by the - * end angle in CCW direction - */ - if (priv->angle_start >= CLUTTER_INT_TO_FIXED (360)) - { - ClutterFixed rounds, a1, a2; - - rounds = priv->angle_start / 360; - a1 = rounds * 360; - a2 = - (priv->angle_start - a1); - - diff = a1 + a2 + priv->angle_end; - } - else - { - diff = CLUTTER_INT_TO_FIXED (360) - - priv->angle_start - + priv->angle_end; - } - - angle = CLUTTER_FIXED_MUL (diff, factor); - angle += priv->angle_start; - } - break; - case CLUTTER_ROTATE_CCW: - if (priv->angle_end <= priv->angle_start) - { - angle = CLUTTER_FIXED_MUL (factor, - (priv->angle_start - priv->angle_end)); - angle = priv->angle_start - angle; - } - else - { - /* Work out the angular length of the arch represented by the - * end angle in CCW direction - */ - if (priv->angle_end >= CLUTTER_INT_TO_FIXED (360)) - { - ClutterFixed rounds, a1, a2; - - rounds = priv->angle_end / 360; - a1 = rounds * 360; - a2 = - (priv->angle_end - a1); - - diff = a1 + a2 + priv->angle_start; - } - else - { - diff = CLUTTER_INT_TO_FIXED (360) - - priv->angle_end - + priv->angle_start; - } - angle = priv->angle_start - CLUTTER_FIXED_MUL (diff, factor); - } - break; + end += CFX_360; } + else if (priv->direction == CLUTTER_ROTATE_CCW && start <= end) + { + end -= CFX_360; + } + + angle = CFX_MUL ((end - start), factor) + start; clutter_behaviour_actors_foreach (behaviour, alpha_notify_foreach, @@ -302,14 +261,14 @@ clutter_behaviour_rotate_class_init (ClutterBehaviourRotateClass *klass) "Angle Begin", "Initial angle", 0.0, - CLUTTER_ANGLE_MAX_DEG, + 360.0, 0.0, CLUTTER_PARAM_READWRITE)); /** * ClutterBehaviourRotate:angle-end: * * The final angle to where the rotation should end. - * + * * Since: 0.4 */ g_object_class_install_property (gobject_class, @@ -318,8 +277,8 @@ clutter_behaviour_rotate_class_init (ClutterBehaviourRotateClass *klass) "Angle End", "Final angle", 0.0, - CLUTTER_ANGLE_MAX_DEG, 360.0, + 0.0, CLUTTER_PARAM_READWRITE)); /** * ClutterBehaviourRotate:axis: @@ -354,7 +313,7 @@ clutter_behaviour_rotate_class_init (ClutterBehaviourRotateClass *klass) /** * ClutterBehaviourRotate:center-x: * - * The x center of rotation. + * The x center of rotation. * * Since: 0.4 */ @@ -370,7 +329,7 @@ clutter_behaviour_rotate_class_init (ClutterBehaviourRotateClass *klass) /** * ClutterBehaviourRotate:center-y: * - * The y center of rotation. + * The y center of rotation. * * Since: 0.4 */ @@ -385,7 +344,7 @@ clutter_behaviour_rotate_class_init (ClutterBehaviourRotateClass *klass) /** * ClutterBehaviourRotate:center-z: * - * The z center of rotation. + * The z center of rotation. * * Since: 0.4 */ @@ -409,7 +368,7 @@ clutter_behaviour_rotate_init (ClutterBehaviourRotate *rotate) rotate->priv = priv = CLUTTER_BEHAVIOUR_ROTATE_GET_PRIVATE (rotate); priv->angle_start = CLUTTER_FLOAT_TO_FIXED (0.0); - priv->angle_end = CLUTTER_FLOAT_TO_FIXED (360.0); + priv->angle_end = CLUTTER_FLOAT_TO_FIXED (0.0); priv->axis = CLUTTER_Z_AXIS; priv->direction = CLUTTER_ROTATE_CW; priv->center_x = priv->center_y = priv->center_z = 0; @@ -420,12 +379,14 @@ clutter_behaviour_rotate_init (ClutterBehaviourRotate *rotate) * @alpha: a #ClutterAlpha, or %NULL * @axis: the rotation axis * @direction: the rotation direction - * @angle_start: the starting angle - * @angle_end: the final angle + * @angle_start: the starting angle in degrees, between 0 and 360. + * @angle_end: the final angle in degrees, between 0 and 360. * * Creates a new #ClutterBehaviourRotate. This behaviour will rotate actors * bound to it on @axis, following @direction, between @angle_start and - * @angle_end. + * @angle_end. Angles >= 360 degrees will be clamped to the canonical interval + * <0, 360), if angle_start == angle_end, the behaviour will carry out a + * single rotation of 360 degrees. * * Return value: the newly created #ClutterBehaviourRotate. * @@ -454,8 +415,10 @@ clutter_behaviour_rotate_new (ClutterAlpha *alpha, * @alpha: a #ClutterAlpha or %NULL * @axis: the rotation axis * @direction: the rotation direction - * @angle_start: the starting angle, in fixed point notation - * @angle_end: the final angle, in fixed point notation + * @angle_start: the starting angle, in fixed point notation in degrees, + * between 0 and 360. + * @angle_end: the final angle, in fixed point notation in degrees, between 0 + * and 360. * * Creates a new #ClutterBehaviourRotate. This is the fixed point version * of clutter_behaviour_rotate_new(). @@ -486,8 +449,8 @@ clutter_behaviour_rotate_newx (ClutterAlpha *alpha, * and then back again to fixed. */ priv = CLUTTER_BEHAVIOUR_ROTATE_GET_PRIVATE (retval); - priv->angle_start = angle_start; - priv->angle_end = angle_end; + priv->angle_start = clamp_angle (angle_start); + priv->angle_end = clamp_angle (angle_end); return retval; } @@ -614,10 +577,11 @@ clutter_behaviour_rotate_get_bounds (ClutterBehaviourRotate *rotate, /** * clutter_behaviour_rotate_set_bounds: * @rotate: a #ClutterBehaviourRotate - * @angle_start: initial angle - * @angle_end: final angle + * @angle_start: initial angle in degrees, between 0 and 360. + * @angle_end: final angle in degrees, between 0 and 360. * - * Sets the initial and final angles of a rotation behaviour. + * Sets the initial and final angles of a rotation behaviour; angles >= 360 + * degrees get clamped to the canonical interval <0, 360). * * Since: 0.4 */ @@ -650,9 +614,9 @@ clutter_behaviour_rotate_get_boundsx (ClutterBehaviourRotate *rotate, ClutterFixed *angle_end) { ClutterBehaviourRotatePrivate *priv; - + g_return_if_fail (CLUTTER_IS_BEHAVIOUR_ROTATE (rotate)); - + priv = rotate->priv; if (angle_start); @@ -665,8 +629,10 @@ clutter_behaviour_rotate_get_boundsx (ClutterBehaviourRotate *rotate, /** * clutter_behaviour_rotate_set_boundsx: * @rotate: a #ClutterBehaviourRotate - * @angle_start: initial angle, in fixed point notation - * @angle_end: final angle, in fixed point notation + * @angle_start: initial angle, in fixed point notation in degrees, between 0 + * and 360. + * @angle_end: final angle, in fixed point notation in degress, between 0 and + * 360. * * Fixed point version of clutter_behaviour_rotate_set_bounds(). * @@ -678,7 +644,7 @@ clutter_behaviour_rotate_set_boundsx (ClutterBehaviourRotate *rotate, ClutterFixed angle_end) { ClutterBehaviourRotatePrivate *priv; - + g_return_if_fail (CLUTTER_IS_BEHAVIOUR_ROTATE (rotate)); priv = rotate->priv; @@ -688,14 +654,14 @@ clutter_behaviour_rotate_set_boundsx (ClutterBehaviourRotate *rotate, if (priv->angle_start != angle_start) { - priv->angle_start = angle_start; + priv->angle_start = clamp_angle (angle_start); g_object_notify (G_OBJECT (rotate), "angle-start"); } if (priv->angle_end != angle_end) { - priv->angle_end = angle_end; + priv->angle_end = clamp_angle (angle_end); g_object_notify (G_OBJECT (rotate), "angle-end"); }