2007-12-17 Tomas Frydrych <tf@openedhand.com>

* clutter/clutter-behaviour-ellipse.c:
	* clutter/clutter-behaviour-rotate.c:
	Clamping of start and end angles to <0, 360).
This commit is contained in:
Tomas Frydrych 2007-12-17 17:16:49 +00:00
parent c4e9f32034
commit 967710c836
3 changed files with 123 additions and 164 deletions

View File

@ -1,3 +1,9 @@
2007-12-17 Tomas Frydrych <tf@openedhand.com>
* clutter/clutter-behaviour-ellipse.c:
* clutter/clutter-behaviour-rotate.c:
Clamping of start and end angles to <0, 360).
2007-12-17 Emmanuele Bassi <ebassi@openedhand.com> 2007-12-17 Emmanuele Bassi <ebassi@openedhand.com>
* clutter/clutter-behaviour-path.c: Clarify the equivalence * clutter/clutter-behaviour-path.c: Clarify the equivalence

View File

@ -183,74 +183,45 @@ actor_apply_knot_foreach (ClutterBehaviour *behave,
clutter_actor_set_depth (actor, knot->z); 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 static void
clutter_behaviour_ellipse_alpha_notify (ClutterBehaviour *behave, clutter_behaviour_ellipse_alpha_notify (ClutterBehaviour *behave,
guint32 alpha) guint32 alpha)
{ {
ClutterBehaviourEllipse *self = CLUTTER_BEHAVIOUR_ELLIPSE (behave); ClutterBehaviourEllipse *self = CLUTTER_BEHAVIOUR_ELLIPSE (behave);
ClutterBehaviourEllipsePrivate *priv = self->priv; ClutterBehaviourEllipsePrivate *priv = self->priv;
ClutterAngle start, end;
knot3d knot; knot3d knot;
ClutterAngle angle = 0; ClutterAngle angle = 0;
if ((priv->angle_end >= priv->angle_start && start = priv->angle_start;
priv->direction == CLUTTER_ROTATE_CW) || end = priv->angle_end;
(priv->angle_end < priv->angle_start &&
priv->direction == CLUTTER_ROTATE_CCW))
{
angle = (priv->angle_end - priv->angle_start) * alpha
/ CLUTTER_ALPHA_MAX_ALPHA
+ priv->angle_start;
}
else if (priv->angle_end >= priv->angle_start &&
priv->direction == CLUTTER_ROTATE_CCW)
{
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 if (priv->direction == CLUTTER_ROTATE_CW && start >= end)
* end angle in CCW direction
*/
if (angle_end >= 1024)
{ {
gint rounds = angle_end / 1024; end += 1024;
ClutterAngle a1 = rounds * 1024;
ClutterAngle a2 = - (angle_end - a1);
diff = a1 + a2 + angle_start;
} }
else else if (priv->direction == CLUTTER_ROTATE_CCW && start <= end)
{ {
diff = 1024 - angle_end + angle_start; end -= 1024;
} }
angle = priv->angle_start - (diff * alpha / CLUTTER_ALPHA_MAX_ALPHA); angle = (end - start) * alpha / CLUTTER_ALPHA_MAX_ALPHA + start;
}
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);
}
clutter_behaviour_ellipse_advance (self, angle, &knot); clutter_behaviour_ellipse_advance (self, angle, &knot);
@ -409,7 +380,7 @@ clutter_behaviour_ellipse_class_init (ClutterBehaviourEllipseClass *klass)
"Start Angle", "Start Angle",
"Initial angle", "Initial angle",
0.0, 0.0,
CLUTTER_ANGLE_MAX_DEG, 360.0,
0.0, 0.0,
CLUTTER_PARAM_READWRITE)); CLUTTER_PARAM_READWRITE));
/** /**
@ -425,8 +396,8 @@ clutter_behaviour_ellipse_class_init (ClutterBehaviourEllipseClass *klass)
"End Angle", "End Angle",
"Final angle", "Final angle",
0.0, 0.0,
CLUTTER_ANGLE_MAX_DEG,
360.0, 360.0,
0.0,
CLUTTER_PARAM_READWRITE)); CLUTTER_PARAM_READWRITE));
/** /**
* ClutterBehaviourEllipse:angle-tilt-x: * ClutterBehaviourEllipse:angle-tilt-x:
@ -539,6 +510,13 @@ clutter_behaviour_ellipse_init (ClutterBehaviourEllipse * self)
self->priv = priv = CLUTTER_BEHAVIOUR_ELLIPSE_GET_PRIVATE (self); self->priv = priv = CLUTTER_BEHAVIOUR_ELLIPSE_GET_PRIVATE (self);
priv->direction = CLUTTER_ROTATE_CW; 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 * @width: width of the ellipse
* @height: height of the ellipse * @height: height of the ellipse
* @direction: #ClutterRotateDirection of rotation * @direction: #ClutterRotateDirection of rotation
* @start: angle in degrees at which movement starts * @start: angle in degrees at which movement starts, between 0 and 360
* @end: angle in degrees at which movement ends * @end: angle in degrees at which movement ends, between 0 and 360
* *
* Creates a behaviour that drives actors along an elliptical path with * Creates a behaviour that drives actors along an elliptical path with
* given center, width and height; the movement starts at @angle_start * 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 * Return value: the newly created #ClutterBehaviourEllipse
* *
* Since: 0.4 * Since: 0.4
@ -786,9 +767,10 @@ clutter_behaviour_ellipse_get_height (ClutterBehaviourEllipse *self)
/** /**
* clutter_behaviour_ellipse_set_angle_start * clutter_behaviour_ellipse_set_angle_start
* @self: a #ClutterBehaviourEllipse * @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 * Since: 0.6
*/ */
@ -805,9 +787,11 @@ clutter_behaviour_ellipse_set_angle_start (ClutterBehaviourEllipse *self,
/** /**
* clutter_behaviour_ellipse_set_angle_startx * clutter_behaviour_ellipse_set_angle_startx
* @self: a #ClutterBehaviourEllipse * @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 * Since: 0.6
*/ */
@ -819,7 +803,7 @@ clutter_behaviour_ellipse_set_angle_startx (ClutterBehaviourEllipse *self,
ClutterAngle new_angle; ClutterAngle new_angle;
g_return_if_fail (CLUTTER_IS_BEHAVIOUR_ELLIPSE (self)); 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; priv = self->priv;
if (priv->angle_start != new_angle) if (priv->angle_start != new_angle)
@ -868,9 +852,10 @@ clutter_behaviour_ellipse_get_angle_startx (ClutterBehaviourEllipse *self)
/** /**
* clutter_behaviour_ellipse_set_angle_end * clutter_behaviour_ellipse_set_angle_end
* @self: a #ClutterBehaviourEllipse * @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 * Since: 0.4
*/ */
@ -887,9 +872,11 @@ clutter_behaviour_ellipse_set_angle_end (ClutterBehaviourEllipse *self,
/** /**
* clutter_behaviour_ellipse_set_angle_endx * clutter_behaviour_ellipse_set_angle_endx
* @self: a #ClutterBehaviourEllipse * @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 * Since: 0.4
*/ */
@ -902,7 +889,7 @@ clutter_behaviour_ellipse_set_angle_endx (ClutterBehaviourEllipse *self,
g_return_if_fail (CLUTTER_IS_BEHAVIOUR_ELLIPSE (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; priv = self->priv;

View File

@ -102,11 +102,24 @@ alpha_notify_foreach (ClutterBehaviour *behaviour,
priv->center_z); 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 static void
clutter_behaviour_rotate_alpha_notify (ClutterBehaviour *behaviour, clutter_behaviour_rotate_alpha_notify (ClutterBehaviour *behaviour,
guint32 alpha_value) guint32 alpha_value)
{ {
ClutterFixed factor, angle, diff; ClutterFixed factor, angle, start, end;
ClutterBehaviourRotate *rotate_behaviour; ClutterBehaviourRotate *rotate_behaviour;
ClutterBehaviourRotatePrivate *priv; ClutterBehaviourRotatePrivate *priv;
@ -116,73 +129,19 @@ clutter_behaviour_rotate_alpha_notify (ClutterBehaviour *behaviour,
factor = CLUTTER_INT_TO_FIXED (alpha_value) / CLUTTER_ALPHA_MAX_ALPHA; factor = CLUTTER_INT_TO_FIXED (alpha_value) / CLUTTER_ALPHA_MAX_ALPHA;
angle = 0; angle = 0;
switch (priv->direction) start = priv->angle_start;
{ end = priv->angle_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; if (priv->direction == CLUTTER_ROTATE_CW && start >= end)
a1 = rounds * 360;
a2 = - (priv->angle_start - a1);
diff = a1 + a2 + priv->angle_end;
}
else
{ {
diff = CLUTTER_INT_TO_FIXED (360) end += CFX_360;
- priv->angle_start }
+ priv->angle_end; else if (priv->direction == CLUTTER_ROTATE_CCW && start <= end)
{
end -= CFX_360;
} }
angle = CLUTTER_FIXED_MUL (diff, factor); angle = CFX_MUL ((end - start), factor) + start;
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;
}
clutter_behaviour_actors_foreach (behaviour, clutter_behaviour_actors_foreach (behaviour,
alpha_notify_foreach, alpha_notify_foreach,
@ -302,7 +261,7 @@ clutter_behaviour_rotate_class_init (ClutterBehaviourRotateClass *klass)
"Angle Begin", "Angle Begin",
"Initial angle", "Initial angle",
0.0, 0.0,
CLUTTER_ANGLE_MAX_DEG, 360.0,
0.0, 0.0,
CLUTTER_PARAM_READWRITE)); CLUTTER_PARAM_READWRITE));
/** /**
@ -318,8 +277,8 @@ clutter_behaviour_rotate_class_init (ClutterBehaviourRotateClass *klass)
"Angle End", "Angle End",
"Final angle", "Final angle",
0.0, 0.0,
CLUTTER_ANGLE_MAX_DEG,
360.0, 360.0,
0.0,
CLUTTER_PARAM_READWRITE)); CLUTTER_PARAM_READWRITE));
/** /**
* ClutterBehaviourRotate:axis: * ClutterBehaviourRotate:axis:
@ -409,7 +368,7 @@ clutter_behaviour_rotate_init (ClutterBehaviourRotate *rotate)
rotate->priv = priv = CLUTTER_BEHAVIOUR_ROTATE_GET_PRIVATE (rotate); rotate->priv = priv = CLUTTER_BEHAVIOUR_ROTATE_GET_PRIVATE (rotate);
priv->angle_start = CLUTTER_FLOAT_TO_FIXED (0.0); 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->axis = CLUTTER_Z_AXIS;
priv->direction = CLUTTER_ROTATE_CW; priv->direction = CLUTTER_ROTATE_CW;
priv->center_x = priv->center_y = priv->center_z = 0; 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 * @alpha: a #ClutterAlpha, or %NULL
* @axis: the rotation axis * @axis: the rotation axis
* @direction: the rotation direction * @direction: the rotation direction
* @angle_start: the starting angle * @angle_start: the starting angle in degrees, between 0 and 360.
* @angle_end: the final angle * @angle_end: the final angle in degrees, between 0 and 360.
* *
* Creates a new #ClutterBehaviourRotate. This behaviour will rotate actors * Creates a new #ClutterBehaviourRotate. This behaviour will rotate actors
* bound to it on @axis, following @direction, between @angle_start and * 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. * Return value: the newly created #ClutterBehaviourRotate.
* *
@ -454,8 +415,10 @@ clutter_behaviour_rotate_new (ClutterAlpha *alpha,
* @alpha: a #ClutterAlpha or %NULL * @alpha: a #ClutterAlpha or %NULL
* @axis: the rotation axis * @axis: the rotation axis
* @direction: the rotation direction * @direction: the rotation direction
* @angle_start: the starting angle, in fixed point notation * @angle_start: the starting angle, in fixed point notation in degrees,
* @angle_end: the final angle, in fixed point notation * 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 * Creates a new #ClutterBehaviourRotate. This is the fixed point version
* of clutter_behaviour_rotate_new(). * of clutter_behaviour_rotate_new().
@ -486,8 +449,8 @@ clutter_behaviour_rotate_newx (ClutterAlpha *alpha,
* and then back again to fixed. * and then back again to fixed.
*/ */
priv = CLUTTER_BEHAVIOUR_ROTATE_GET_PRIVATE (retval); priv = CLUTTER_BEHAVIOUR_ROTATE_GET_PRIVATE (retval);
priv->angle_start = angle_start; priv->angle_start = clamp_angle (angle_start);
priv->angle_end = angle_end; priv->angle_end = clamp_angle (angle_end);
return retval; return retval;
} }
@ -614,10 +577,11 @@ clutter_behaviour_rotate_get_bounds (ClutterBehaviourRotate *rotate,
/** /**
* clutter_behaviour_rotate_set_bounds: * clutter_behaviour_rotate_set_bounds:
* @rotate: a #ClutterBehaviourRotate * @rotate: a #ClutterBehaviourRotate
* @angle_start: initial angle * @angle_start: initial angle in degrees, between 0 and 360.
* @angle_end: final angle * @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 * Since: 0.4
*/ */
@ -665,8 +629,10 @@ clutter_behaviour_rotate_get_boundsx (ClutterBehaviourRotate *rotate,
/** /**
* clutter_behaviour_rotate_set_boundsx: * clutter_behaviour_rotate_set_boundsx:
* @rotate: a #ClutterBehaviourRotate * @rotate: a #ClutterBehaviourRotate
* @angle_start: initial angle, in fixed point notation * @angle_start: initial angle, in fixed point notation in degrees, between 0
* @angle_end: final angle, in fixed point notation * 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(). * Fixed point version of clutter_behaviour_rotate_set_bounds().
* *
@ -688,14 +654,14 @@ clutter_behaviour_rotate_set_boundsx (ClutterBehaviourRotate *rotate,
if (priv->angle_start != angle_start) 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"); g_object_notify (G_OBJECT (rotate), "angle-start");
} }
if (priv->angle_end != angle_end) 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"); g_object_notify (G_OBJECT (rotate), "angle-end");
} }