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>
* 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);
}
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;

View File

@ -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;
@ -116,73 +129,19 @@ 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,7 +261,7 @@ clutter_behaviour_rotate_class_init (ClutterBehaviourRotateClass *klass)
"Angle Begin",
"Initial angle",
0.0,
CLUTTER_ANGLE_MAX_DEG,
360.0,
0.0,
CLUTTER_PARAM_READWRITE));
/**
@ -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:
@ -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
*/
@ -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().
*
@ -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");
}