79acb088e7
Since using addresses that might change is something that finally the FSF acknowledge as a plausible scenario (after changing address twice), the license blurb in the source files should use the URI for getting the license in case the library did not come with it. Not that URIs cannot possibly change, but at least it's easier to set up a redirection at the same place. As a side note: this commit closes the oldes bug in Clutter's bug report tool. http://bugzilla.openedhand.com/show_bug.cgi?id=521
1040 lines
27 KiB
C
1040 lines
27 KiB
C
|
|
/* -*- mode:C; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
|
/*
|
|
* Clutter.
|
|
*
|
|
* An OpenGL based 'interactive canvas' library.
|
|
*
|
|
* Authored By Tomas Frydrych <tf@openedhand.com>
|
|
*
|
|
* Copyright (C) 2007 OpenedHand Ltd
|
|
* Copyright (C) 2009 Intel Corp.
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
/**
|
|
* SECTION:clutter-behaviour-ellipse
|
|
* @short_description: A behaviour interpolating position along an ellipse
|
|
*
|
|
* #ClutterBehaviourEllipse interpolates actors along a path defined by
|
|
* an ellipse.
|
|
*
|
|
* <note><para>When applying an ellipse behaviour to an actor, the
|
|
* behaviour will update the actor's position and depth and set them
|
|
* to what is dictated by the ellipses initial position.</para></note>
|
|
*
|
|
* Since: 0.4
|
|
*/
|
|
|
|
#include "clutter-fixed.h"
|
|
#include "clutter-marshal.h"
|
|
#include "clutter-behaviour-ellipse.h"
|
|
#include "clutter-debug.h"
|
|
#include "clutter-enum-types.h"
|
|
#include "clutter-private.h"
|
|
|
|
#include <stdlib.h>
|
|
#include <memory.h>
|
|
|
|
G_DEFINE_TYPE (ClutterBehaviourEllipse,
|
|
clutter_behaviour_ellipse,
|
|
CLUTTER_TYPE_BEHAVIOUR);
|
|
|
|
#define CLUTTER_BEHAVIOUR_ELLIPSE_GET_PRIVATE(obj) \
|
|
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), \
|
|
CLUTTER_TYPE_BEHAVIOUR_ELLIPSE, \
|
|
ClutterBehaviourEllipsePrivate))
|
|
|
|
enum
|
|
{
|
|
PROP_0,
|
|
|
|
PROP_CENTER,
|
|
PROP_WIDTH,
|
|
PROP_HEIGHT,
|
|
PROP_ANGLE_START,
|
|
PROP_ANGLE_END,
|
|
PROP_ANGLE_TILT_X,
|
|
PROP_ANGLE_TILT_Y,
|
|
PROP_ANGLE_TILT_Z,
|
|
PROP_DIRECTION,
|
|
};
|
|
|
|
struct _ClutterBehaviourEllipsePrivate
|
|
{
|
|
ClutterKnot center;
|
|
|
|
/* a = width / 2 */
|
|
gint a;
|
|
|
|
/* b = height / 2 */
|
|
gint b;
|
|
|
|
gdouble angle_start;
|
|
gdouble angle_end;
|
|
|
|
gdouble angle_tilt_x;
|
|
gdouble angle_tilt_y;
|
|
gdouble angle_tilt_z;
|
|
|
|
ClutterRotateDirection direction;
|
|
};
|
|
|
|
typedef struct _knot3d
|
|
{
|
|
gint x;
|
|
gint y;
|
|
gint z;
|
|
} knot3d;
|
|
|
|
static void
|
|
clutter_behaviour_ellipse_advance (ClutterBehaviourEllipse *e,
|
|
float angle,
|
|
knot3d *knot)
|
|
{
|
|
ClutterBehaviourEllipsePrivate *priv = e->priv;
|
|
gint x, y, z;
|
|
|
|
x = priv->a * cosf (angle * (G_PI / 180.0));
|
|
y = priv->b * sinf (angle * (G_PI / 180.0));
|
|
z = 0;
|
|
|
|
if (priv->angle_tilt_z)
|
|
{
|
|
/*
|
|
* x2 = r * cos (angle + tilt_z)
|
|
* y2 = r * sin (angle + tilt_z)
|
|
*
|
|
* These can be trasformed to the formulas below using properties of
|
|
* sin (a + b) and cos (a + b)
|
|
*
|
|
*/
|
|
gfloat x2, y2;
|
|
|
|
x2 = x * cosf (priv->angle_tilt_z * (G_PI / 180.0))
|
|
- y * sinf (priv->angle_tilt_z * (G_PI / 180.0));
|
|
|
|
y2 = y * cosf (priv->angle_tilt_z * (G_PI / 180.0))
|
|
+ x * sinf (priv->angle_tilt_z * (G_PI / 180.0));
|
|
|
|
x = (x2);
|
|
y = (y2);
|
|
}
|
|
|
|
if (priv->angle_tilt_x)
|
|
{
|
|
gfloat z2, y2;
|
|
|
|
z2 = - y * sinf (priv->angle_tilt_x * (G_PI / 180.0));
|
|
y2 = y * cosf (priv->angle_tilt_x * (G_PI / 180.0));
|
|
|
|
z = z2;
|
|
y = y2;
|
|
}
|
|
|
|
if (priv->angle_tilt_y)
|
|
{
|
|
gfloat x2, z2;
|
|
|
|
x2 = x * cosf (priv->angle_tilt_y * (G_PI / 180.0))
|
|
- z * sinf (priv->angle_tilt_y * (G_PI / 180.0));
|
|
|
|
z2 = z * cosf (priv->angle_tilt_y * (G_PI / 180.0))
|
|
+ x * sinf (priv->angle_tilt_y * (G_PI / 180.0));
|
|
|
|
x = x2;
|
|
z = z2;
|
|
}
|
|
|
|
knot->x = x;
|
|
knot->y = y;
|
|
knot->z = z;
|
|
|
|
CLUTTER_NOTE (BEHAVIOUR, "advancing to angle %.2f [%d, %d] (a: %d, b: %d)",
|
|
angle,
|
|
knot->x, knot->y,
|
|
priv->a, priv->b);
|
|
}
|
|
|
|
|
|
static void
|
|
actor_apply_knot_foreach (ClutterBehaviour *behave,
|
|
ClutterActor *actor,
|
|
gpointer data)
|
|
{
|
|
ClutterBehaviourEllipsePrivate *priv;
|
|
knot3d *knot = data;
|
|
|
|
priv = ((ClutterBehaviourEllipse *) behave)->priv;
|
|
|
|
clutter_actor_set_position (actor, knot->x, knot->y);
|
|
|
|
if (priv->angle_tilt_x != 0 || priv->angle_tilt_y != 0)
|
|
clutter_actor_set_depth (actor, knot->z);
|
|
}
|
|
|
|
static inline float
|
|
clamp_angle (float a)
|
|
{
|
|
gint rounds;
|
|
|
|
rounds = a / 360;
|
|
if (a < 0)
|
|
rounds--;
|
|
|
|
return a - 360 * rounds;
|
|
}
|
|
|
|
static void
|
|
clutter_behaviour_ellipse_alpha_notify (ClutterBehaviour *behave,
|
|
gdouble alpha)
|
|
{
|
|
ClutterBehaviourEllipse *self = CLUTTER_BEHAVIOUR_ELLIPSE (behave);
|
|
ClutterBehaviourEllipsePrivate *priv = self->priv;
|
|
gfloat start, end;
|
|
gfloat angle = 0;
|
|
knot3d knot;
|
|
|
|
/* we do everything in single precision because it's easier, even
|
|
* though all the parameters are stored in double precision for
|
|
* consistency with the equivalent ClutterActor API
|
|
*/
|
|
start = priv->angle_start;
|
|
end = priv->angle_end;
|
|
|
|
if (priv->direction == CLUTTER_ROTATE_CW && start >= end)
|
|
end += 360;
|
|
else if (priv->direction == CLUTTER_ROTATE_CCW && start <= end)
|
|
end -= 360;
|
|
|
|
angle = (end - start) * alpha + start;
|
|
|
|
clutter_behaviour_ellipse_advance (self, angle, &knot);
|
|
|
|
knot.x += priv->center.x;
|
|
knot.y += priv->center.y;
|
|
|
|
clutter_behaviour_actors_foreach (behave, actor_apply_knot_foreach, &knot);
|
|
}
|
|
|
|
static void
|
|
clutter_behaviour_ellipse_set_property (GObject *gobject,
|
|
guint prop_id,
|
|
const GValue *value,
|
|
GParamSpec *pspec)
|
|
{
|
|
ClutterBehaviourEllipse *el = CLUTTER_BEHAVIOUR_ELLIPSE (gobject);
|
|
ClutterBehaviourEllipsePrivate *priv = el->priv;
|
|
|
|
switch (prop_id)
|
|
{
|
|
case PROP_ANGLE_START:
|
|
priv->angle_start = g_value_get_double (value);
|
|
break;
|
|
|
|
case PROP_ANGLE_END:
|
|
priv->angle_end = g_value_get_double (value);
|
|
break;
|
|
|
|
case PROP_ANGLE_TILT_X:
|
|
priv->angle_tilt_x = g_value_get_double (value);
|
|
break;
|
|
|
|
case PROP_ANGLE_TILT_Y:
|
|
priv->angle_tilt_y = g_value_get_double (value);
|
|
break;
|
|
|
|
case PROP_ANGLE_TILT_Z:
|
|
priv->angle_tilt_z = g_value_get_double (value);
|
|
break;
|
|
|
|
case PROP_WIDTH:
|
|
clutter_behaviour_ellipse_set_width (el, g_value_get_int (value));
|
|
break;
|
|
|
|
case PROP_HEIGHT:
|
|
clutter_behaviour_ellipse_set_height (el, g_value_get_int (value));
|
|
break;
|
|
|
|
case PROP_CENTER:
|
|
{
|
|
ClutterKnot *knot = g_value_get_boxed (value);
|
|
if (knot)
|
|
clutter_behaviour_ellipse_set_center (el, knot->x, knot->y);
|
|
}
|
|
break;
|
|
|
|
case PROP_DIRECTION:
|
|
priv->direction = g_value_get_enum (value);
|
|
break;
|
|
|
|
default:
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void
|
|
clutter_behaviour_ellipse_get_property (GObject *gobject,
|
|
guint prop_id,
|
|
GValue *value,
|
|
GParamSpec *pspec)
|
|
{
|
|
ClutterBehaviourEllipsePrivate *priv;
|
|
|
|
priv = CLUTTER_BEHAVIOUR_ELLIPSE (gobject)->priv;
|
|
|
|
switch (prop_id)
|
|
{
|
|
case PROP_ANGLE_START:
|
|
g_value_set_double (value, priv->angle_start);
|
|
break;
|
|
|
|
case PROP_ANGLE_END:
|
|
g_value_set_double (value, priv->angle_end);
|
|
break;
|
|
|
|
case PROP_ANGLE_TILT_X:
|
|
g_value_set_double (value, priv->angle_tilt_x);
|
|
break;
|
|
|
|
case PROP_ANGLE_TILT_Y:
|
|
g_value_set_double (value, priv->angle_tilt_y);
|
|
break;
|
|
|
|
case PROP_ANGLE_TILT_Z:
|
|
g_value_set_double (value, priv->angle_tilt_z);
|
|
break;
|
|
|
|
case PROP_WIDTH:
|
|
g_value_set_int (value, (priv->a * 2));
|
|
break;
|
|
|
|
case PROP_HEIGHT:
|
|
g_value_set_int (value, (priv->b * 2));
|
|
break;
|
|
|
|
case PROP_CENTER:
|
|
g_value_set_boxed (value, &priv->center);
|
|
break;
|
|
|
|
case PROP_DIRECTION:
|
|
g_value_set_enum (value, priv->direction);
|
|
break;
|
|
|
|
default:
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void
|
|
clutter_behaviour_ellipse_applied (ClutterBehaviour *behave,
|
|
ClutterActor *actor)
|
|
{
|
|
ClutterBehaviourEllipse *e = CLUTTER_BEHAVIOUR_ELLIPSE (behave);
|
|
ClutterBehaviourEllipsePrivate *priv = e->priv;
|
|
knot3d knot = { 0, };
|
|
|
|
clutter_behaviour_ellipse_advance (e, priv->angle_start, &knot);
|
|
|
|
clutter_actor_set_position (actor, knot.x, knot.y);
|
|
|
|
/* the depth should be changed only if there is a tilt on
|
|
* any of the X or the Y axis
|
|
*/
|
|
if (priv->angle_tilt_x != 0 || priv->angle_tilt_y != 0)
|
|
clutter_actor_set_depth (actor, knot.z);
|
|
}
|
|
|
|
static void
|
|
clutter_behaviour_ellipse_class_init (ClutterBehaviourEllipseClass *klass)
|
|
{
|
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
|
ClutterBehaviourClass *behave_class = CLUTTER_BEHAVIOUR_CLASS (klass);
|
|
GParamSpec *pspec = NULL;
|
|
|
|
g_type_class_add_private (klass, sizeof (ClutterBehaviourEllipsePrivate));
|
|
|
|
object_class->set_property = clutter_behaviour_ellipse_set_property;
|
|
object_class->get_property = clutter_behaviour_ellipse_get_property;
|
|
|
|
behave_class->alpha_notify = clutter_behaviour_ellipse_alpha_notify;
|
|
behave_class->applied = clutter_behaviour_ellipse_applied;
|
|
|
|
/**
|
|
* ClutterBehaviourEllipse:angle-start:
|
|
*
|
|
* The initial angle from where the rotation should start.
|
|
*
|
|
* Since: 0.4
|
|
*/
|
|
pspec = g_param_spec_double ("angle-start",
|
|
"Start Angle",
|
|
"Initial angle",
|
|
0.0, 360.0,
|
|
0.0,
|
|
CLUTTER_PARAM_READWRITE);
|
|
g_object_class_install_property (object_class, PROP_ANGLE_START, pspec);
|
|
|
|
/**
|
|
* ClutterBehaviourEllipse:angle-end:
|
|
*
|
|
* The final angle to where the rotation should end.
|
|
*
|
|
* Since: 0.4
|
|
*/
|
|
pspec = g_param_spec_double ("angle-end",
|
|
"End Angle",
|
|
"Final angle",
|
|
0.0, 360.0,
|
|
0.0,
|
|
CLUTTER_PARAM_READWRITE);
|
|
g_object_class_install_property (object_class, PROP_ANGLE_END, pspec);
|
|
|
|
/**
|
|
* ClutterBehaviourEllipse:angle-tilt-x:
|
|
*
|
|
* The tilt angle for the rotation around center in X axis
|
|
*
|
|
* Since: 0.4
|
|
*/
|
|
pspec = g_param_spec_double ("angle-tilt-x",
|
|
"Angle x tilt",
|
|
"Tilt of the ellipse around x axis",
|
|
0.0, 360.0,
|
|
360.0,
|
|
CLUTTER_PARAM_READWRITE);
|
|
g_object_class_install_property (object_class, PROP_ANGLE_TILT_X, pspec);
|
|
|
|
/**
|
|
* ClutterBehaviourEllipse:angle-tilt-y:
|
|
*
|
|
* The tilt angle for the rotation around center in Y axis
|
|
*
|
|
* Since: 0.4
|
|
*/
|
|
pspec = g_param_spec_double ("angle-tilt-y",
|
|
"Angle y tilt",
|
|
"Tilt of the ellipse around y axis",
|
|
0.0, 360.0,
|
|
360.0,
|
|
CLUTTER_PARAM_READWRITE);
|
|
g_object_class_install_property (object_class, PROP_ANGLE_TILT_Y, pspec);
|
|
|
|
/**
|
|
* ClutterBehaviourEllipse:angle-tilt-z:
|
|
*
|
|
* The tilt angle for the rotation on the Z axis
|
|
*
|
|
* Since: 0.4
|
|
*/
|
|
pspec = g_param_spec_double ("angle-tilt-z",
|
|
"Angle z tilt",
|
|
"Tilt of the ellipse around z axis",
|
|
0.0, 360.0,
|
|
360.0,
|
|
CLUTTER_PARAM_READWRITE);
|
|
g_object_class_install_property (object_class, PROP_ANGLE_TILT_Z, pspec);
|
|
|
|
/**
|
|
* ClutterBehaviourEllipse:width:
|
|
*
|
|
* Width of the ellipse, in pixels
|
|
*
|
|
* Since: 0.4
|
|
*/
|
|
pspec = g_param_spec_int ("width",
|
|
"Width",
|
|
"Width of the ellipse",
|
|
0, G_MAXINT,
|
|
100,
|
|
CLUTTER_PARAM_READWRITE);
|
|
g_object_class_install_property (object_class, PROP_WIDTH, pspec);
|
|
|
|
/**
|
|
* ClutterBehaviourEllipse:height:
|
|
*
|
|
* Height of the ellipse, in pixels
|
|
*
|
|
* Since: 0.4
|
|
*/
|
|
pspec = g_param_spec_int ("height",
|
|
"Height",
|
|
"Height of ellipse",
|
|
0, G_MAXINT,
|
|
50,
|
|
CLUTTER_PARAM_READWRITE);
|
|
g_object_class_install_property (object_class, PROP_HEIGHT, pspec);
|
|
|
|
/**
|
|
* ClutterBehaviourEllipse:center:
|
|
*
|
|
* The center of the ellipse.
|
|
*
|
|
* Since: 0.4
|
|
*/
|
|
pspec = g_param_spec_boxed ("center",
|
|
"Center",
|
|
"Center of ellipse",
|
|
CLUTTER_TYPE_KNOT,
|
|
CLUTTER_PARAM_READWRITE);
|
|
g_object_class_install_property (object_class, PROP_CENTER, pspec);
|
|
|
|
/**
|
|
* ClutterBehaviourEllipse:direction:
|
|
*
|
|
* The direction of the rotation.
|
|
*
|
|
* Since: 0.4
|
|
*/
|
|
pspec = g_param_spec_enum ("direction",
|
|
"Direction",
|
|
"Direction of rotation",
|
|
CLUTTER_TYPE_ROTATE_DIRECTION,
|
|
CLUTTER_ROTATE_CW,
|
|
CLUTTER_PARAM_READWRITE);
|
|
g_object_class_install_property (object_class, PROP_DIRECTION, pspec);
|
|
}
|
|
|
|
static void
|
|
clutter_behaviour_ellipse_init (ClutterBehaviourEllipse * self)
|
|
{
|
|
ClutterBehaviourEllipsePrivate *priv;
|
|
|
|
self->priv = priv = CLUTTER_BEHAVIOUR_ELLIPSE_GET_PRIVATE (self);
|
|
|
|
priv->direction = CLUTTER_ROTATE_CW;
|
|
|
|
priv->angle_start = 0;
|
|
priv->angle_end = 0;
|
|
|
|
priv->a = 50;
|
|
priv->b = 25;
|
|
|
|
priv->angle_tilt_x = 360;
|
|
priv->angle_tilt_y = 360;
|
|
priv->angle_tilt_z = 360;
|
|
}
|
|
|
|
/**
|
|
* clutter_behaviour_ellipse_new:
|
|
* @alpha: a #ClutterAlpha, or %NULL
|
|
* @x: x coordinace of the center
|
|
* @y: y coordiance of the center
|
|
* @width: width of the ellipse
|
|
* @height: height of the ellipse
|
|
* @direction: #ClutterRotateDirection of rotation
|
|
* @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 @start
|
|
* degrees (with 0 corresponding to 12 o'clock) and ends at @end
|
|
* degrees. Angles greated than 360 degrees get clamped to the canonical
|
|
* interval <0, 360); if @start is equal to @end, the behaviour will
|
|
* rotate by exacly 360 degrees.
|
|
*
|
|
* Return value: the newly created #ClutterBehaviourEllipse
|
|
*
|
|
* Since: 0.4
|
|
*/
|
|
ClutterBehaviour *
|
|
clutter_behaviour_ellipse_new (ClutterAlpha *alpha,
|
|
gint x,
|
|
gint y,
|
|
gint width,
|
|
gint height,
|
|
ClutterRotateDirection direction,
|
|
gdouble start,
|
|
gdouble end)
|
|
{
|
|
ClutterKnot center;
|
|
|
|
g_return_val_if_fail (alpha == NULL || CLUTTER_IS_ALPHA (alpha), NULL);
|
|
|
|
center.x = x;
|
|
center.y = y;
|
|
|
|
return g_object_new (CLUTTER_TYPE_BEHAVIOUR_ELLIPSE,
|
|
"alpha", alpha,
|
|
"center", ¢er,
|
|
"width", width,
|
|
"height", height,
|
|
"direction", direction,
|
|
"angle-start", start,
|
|
"angle-end", end,
|
|
NULL);
|
|
}
|
|
|
|
/**
|
|
* clutter_behaviour_ellipse_set_center:
|
|
* @self: a #ClutterBehaviourEllipse
|
|
* @x: x coordinace of centre
|
|
* @y: y coordinace of centre
|
|
*
|
|
* Sets the center of the elliptical path to the point represented by knot.
|
|
*
|
|
* Since: 0.4
|
|
*/
|
|
void
|
|
clutter_behaviour_ellipse_set_center (ClutterBehaviourEllipse *self,
|
|
gint x,
|
|
gint y)
|
|
{
|
|
ClutterBehaviourEllipsePrivate *priv;
|
|
|
|
g_return_if_fail (CLUTTER_IS_BEHAVIOUR_ELLIPSE (self));
|
|
|
|
priv = self->priv;
|
|
|
|
if (priv->center.x != x || priv->center.y != y)
|
|
{
|
|
priv->center.x = x;
|
|
priv->center.y = y;
|
|
|
|
g_object_notify (G_OBJECT (self), "center");
|
|
}
|
|
}
|
|
|
|
/**
|
|
* clutter_behaviour_ellipse_get_center:
|
|
* @self: a #ClutterBehaviourEllipse
|
|
* @x: return location for the X coordinate of the center, or %NULL
|
|
* @y: return location for the Y coordinate of the center, or %NULL
|
|
*
|
|
* Gets the center of the elliptical path path.
|
|
*
|
|
* Since: 0.4
|
|
*/
|
|
void
|
|
clutter_behaviour_ellipse_get_center (ClutterBehaviourEllipse *self,
|
|
gint *x,
|
|
gint *y)
|
|
{
|
|
ClutterBehaviourEllipsePrivate *priv;
|
|
|
|
g_return_if_fail (CLUTTER_IS_BEHAVIOUR_ELLIPSE (self));
|
|
|
|
priv = self->priv;
|
|
|
|
if (x)
|
|
*x = priv->center.x;
|
|
|
|
if (y)
|
|
*y = priv->center.y;
|
|
}
|
|
|
|
|
|
/**
|
|
* clutter_behaviour_ellipse_set_width:
|
|
* @self: a #ClutterBehaviourEllipse
|
|
* @width: width of the ellipse
|
|
*
|
|
* Sets the width of the elliptical path.
|
|
*
|
|
* Since: 0.4
|
|
*/
|
|
void
|
|
clutter_behaviour_ellipse_set_width (ClutterBehaviourEllipse *self,
|
|
gint width)
|
|
{
|
|
ClutterBehaviourEllipsePrivate *priv;
|
|
|
|
g_return_if_fail (CLUTTER_IS_BEHAVIOUR_ELLIPSE (self));
|
|
|
|
priv = self->priv;
|
|
|
|
if (priv->a != width / 2)
|
|
{
|
|
priv->a = width / 2;
|
|
|
|
g_object_notify (G_OBJECT (self), "width");
|
|
}
|
|
}
|
|
|
|
/**
|
|
* clutter_behaviour_ellipse_get_width:
|
|
* @self: a #ClutterBehaviourEllipse
|
|
*
|
|
* Gets the width of the elliptical path.
|
|
*
|
|
* Return value: the width of the path
|
|
*
|
|
* Since: 0.4
|
|
*/
|
|
gint
|
|
clutter_behaviour_ellipse_get_width (ClutterBehaviourEllipse *self)
|
|
{
|
|
g_return_val_if_fail (CLUTTER_IS_BEHAVIOUR_ELLIPSE (self), 0);
|
|
|
|
return self->priv->a * 2;
|
|
}
|
|
|
|
/**
|
|
* clutter_behaviour_ellipse_set_height:
|
|
* @self: a #ClutterBehaviourEllipse
|
|
* @height: height of the ellipse
|
|
*
|
|
* Sets the height of the elliptical path.
|
|
*
|
|
* Since: 0.4
|
|
*/
|
|
void
|
|
clutter_behaviour_ellipse_set_height (ClutterBehaviourEllipse *self,
|
|
gint height)
|
|
{
|
|
ClutterBehaviourEllipsePrivate *priv;
|
|
|
|
g_return_if_fail (CLUTTER_IS_BEHAVIOUR_ELLIPSE (self));
|
|
|
|
priv = self->priv;
|
|
|
|
if (priv->b != height / 2)
|
|
{
|
|
priv->b = height / 2;
|
|
|
|
g_object_notify (G_OBJECT (self), "height");
|
|
}
|
|
}
|
|
|
|
/**
|
|
* clutter_behaviour_ellipse_get_height:
|
|
* @self: a #ClutterBehaviourEllipse
|
|
*
|
|
* Gets the height of the elliptical path.
|
|
*
|
|
* Return value: the height of the path
|
|
*
|
|
* Since: 0.4
|
|
*/
|
|
gint
|
|
clutter_behaviour_ellipse_get_height (ClutterBehaviourEllipse *self)
|
|
{
|
|
g_return_val_if_fail (CLUTTER_IS_BEHAVIOUR_ELLIPSE (self), 0);
|
|
|
|
return self->priv->b * 2;
|
|
}
|
|
|
|
/**
|
|
* clutter_behaviour_ellipse_set_angle_start:
|
|
* @self: a #ClutterBehaviourEllipse
|
|
* @angle_start: angle at which movement starts in degrees, between 0 and 360.
|
|
*
|
|
* Sets the angle at which movement starts; angles >= 360 degress get clamped
|
|
* to the canonical interval <0, 360).
|
|
*
|
|
* Since: 0.6
|
|
*/
|
|
void
|
|
clutter_behaviour_ellipse_set_angle_start (ClutterBehaviourEllipse *self,
|
|
gdouble angle_start)
|
|
{
|
|
ClutterBehaviourEllipsePrivate *priv;
|
|
gdouble new_angle;
|
|
|
|
g_return_if_fail (CLUTTER_IS_BEHAVIOUR_ELLIPSE (self));
|
|
|
|
new_angle = clamp_angle (angle_start);
|
|
|
|
priv = self->priv;
|
|
|
|
if (priv->angle_start != new_angle)
|
|
{
|
|
priv->angle_start = new_angle;
|
|
g_object_notify (G_OBJECT (self), "angle-start");
|
|
}
|
|
}
|
|
|
|
/**
|
|
* clutter_behaviour_ellipse_get_angle_start:
|
|
* @self: a #ClutterBehaviourEllipse
|
|
*
|
|
* Gets the angle at which movements starts.
|
|
*
|
|
* Return value: angle in degrees
|
|
*
|
|
* Since: 0.6
|
|
*/
|
|
gdouble
|
|
clutter_behaviour_ellipse_get_angle_start (ClutterBehaviourEllipse *self)
|
|
{
|
|
g_return_val_if_fail (CLUTTER_IS_BEHAVIOUR_ELLIPSE (self), 0.0);
|
|
|
|
return self->priv->angle_start;
|
|
}
|
|
|
|
/**
|
|
* clutter_behaviour_ellipse_set_angle_end:
|
|
* @self: a #ClutterBehaviourEllipse
|
|
* @angle_end: angle at which movement ends in degrees, between 0 and 360.
|
|
*
|
|
* Sets the angle at which movement ends; angles >= 360 degress get clamped
|
|
* to the canonical interval <0, 360).
|
|
*
|
|
* Since: 0.4
|
|
*/
|
|
void
|
|
clutter_behaviour_ellipse_set_angle_end (ClutterBehaviourEllipse *self,
|
|
gdouble angle_end)
|
|
{
|
|
ClutterBehaviourEllipsePrivate *priv;
|
|
gdouble new_angle;
|
|
|
|
g_return_if_fail (CLUTTER_IS_BEHAVIOUR_ELLIPSE (self));
|
|
|
|
new_angle = clamp_angle (angle_end);
|
|
|
|
priv = self->priv;
|
|
|
|
if (priv->angle_end != new_angle)
|
|
{
|
|
priv->angle_end = new_angle;
|
|
|
|
g_object_notify (G_OBJECT (self), "angle-end");
|
|
}
|
|
}
|
|
|
|
/**
|
|
* clutter_behaviour_ellipse_get_angle_end:
|
|
* @self: a #ClutterBehaviourEllipse
|
|
*
|
|
* Gets the at which movements ends.
|
|
*
|
|
* Return value: angle in degrees
|
|
*
|
|
* Since: 0.4
|
|
*/
|
|
gdouble
|
|
clutter_behaviour_ellipse_get_angle_end (ClutterBehaviourEllipse *self)
|
|
{
|
|
g_return_val_if_fail (CLUTTER_IS_BEHAVIOUR_ELLIPSE (self), 0.0);
|
|
|
|
return self->priv->angle_end;
|
|
}
|
|
|
|
/**
|
|
* clutter_behaviour_ellipse_set_angle_tilt:
|
|
* @self: a #ClutterBehaviourEllipse
|
|
* @axis: a #ClutterRotateAxis
|
|
* @angle_tilt: tilt of the elipse around the center in the given axis in
|
|
* degrees.
|
|
*
|
|
* Sets the angle at which the ellipse should be tilted around it's center.
|
|
*
|
|
* Since: 0.4
|
|
*/
|
|
void
|
|
clutter_behaviour_ellipse_set_angle_tilt (ClutterBehaviourEllipse *self,
|
|
ClutterRotateAxis axis,
|
|
gdouble angle_tilt)
|
|
{
|
|
ClutterBehaviourEllipsePrivate *priv;
|
|
|
|
g_return_if_fail (CLUTTER_IS_BEHAVIOUR_ELLIPSE (self));
|
|
|
|
priv = self->priv;
|
|
|
|
switch (axis)
|
|
{
|
|
case CLUTTER_X_AXIS:
|
|
if (priv->angle_tilt_x != angle_tilt)
|
|
{
|
|
priv->angle_tilt_x = angle_tilt;
|
|
|
|
g_object_notify (G_OBJECT (self), "angle-tilt-x");
|
|
}
|
|
break;
|
|
|
|
case CLUTTER_Y_AXIS:
|
|
if (priv->angle_tilt_y != angle_tilt)
|
|
{
|
|
priv->angle_tilt_y = angle_tilt;
|
|
|
|
g_object_notify (G_OBJECT (self), "angle-tilt-y");
|
|
}
|
|
break;
|
|
|
|
case CLUTTER_Z_AXIS:
|
|
if (priv->angle_tilt_z != angle_tilt)
|
|
{
|
|
priv->angle_tilt_z = angle_tilt;
|
|
|
|
g_object_notify (G_OBJECT (self), "angle-tilt-z");
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* clutter_behaviour_ellipse_get_angle_tilt:
|
|
* @self: a #ClutterBehaviourEllipse
|
|
* @axis: a #ClutterRotateAxis
|
|
*
|
|
* Gets the tilt of the ellipse around the center in the given axis.
|
|
*
|
|
* Return value: angle in degrees.
|
|
*
|
|
* Since: 0.4
|
|
*/
|
|
gdouble
|
|
clutter_behaviour_ellipse_get_angle_tilt (ClutterBehaviourEllipse *self,
|
|
ClutterRotateAxis axis)
|
|
{
|
|
g_return_val_if_fail (CLUTTER_IS_BEHAVIOUR_ELLIPSE (self), 0.0);
|
|
|
|
switch (axis)
|
|
{
|
|
case CLUTTER_X_AXIS:
|
|
return self->priv->angle_tilt_x;
|
|
|
|
case CLUTTER_Y_AXIS:
|
|
return self->priv->angle_tilt_y;
|
|
|
|
case CLUTTER_Z_AXIS:
|
|
return self->priv->angle_tilt_z;
|
|
}
|
|
|
|
return 0.0;
|
|
}
|
|
|
|
/**
|
|
* clutter_behaviour_ellipse_set_tilt:
|
|
* @self: a #ClutterBehaviourEllipse
|
|
* @angle_tilt_x: tilt of the elipse around the center in X axis in degrees.
|
|
* @angle_tilt_y: tilt of the elipse around the center in Y axis in degrees.
|
|
* @angle_tilt_z: tilt of the elipse around the center in Z axis in degrees.
|
|
*
|
|
* Sets the angles at which the ellipse should be tilted around it's center.
|
|
*
|
|
* Since: 0.4
|
|
*/
|
|
void
|
|
clutter_behaviour_ellipse_set_tilt (ClutterBehaviourEllipse *self,
|
|
gdouble angle_tilt_x,
|
|
gdouble angle_tilt_y,
|
|
gdouble angle_tilt_z)
|
|
{
|
|
ClutterBehaviourEllipsePrivate *priv;
|
|
|
|
g_return_if_fail (CLUTTER_IS_BEHAVIOUR_ELLIPSE (self));
|
|
|
|
priv = self->priv;
|
|
|
|
g_object_freeze_notify (G_OBJECT (self));
|
|
|
|
if (priv->angle_tilt_x != angle_tilt_x)
|
|
{
|
|
priv->angle_tilt_x = angle_tilt_x;
|
|
|
|
g_object_notify (G_OBJECT (self), "angle-tilt-x");
|
|
}
|
|
|
|
if (priv->angle_tilt_y != angle_tilt_y)
|
|
{
|
|
priv->angle_tilt_y = angle_tilt_y;
|
|
|
|
g_object_notify (G_OBJECT (self), "angle-tilt-y");
|
|
}
|
|
|
|
if (priv->angle_tilt_z != angle_tilt_z)
|
|
{
|
|
priv->angle_tilt_z = angle_tilt_z;
|
|
|
|
g_object_notify (G_OBJECT (self), "angle-tilt-z");
|
|
}
|
|
|
|
g_object_thaw_notify (G_OBJECT (self));
|
|
}
|
|
|
|
/**
|
|
* clutter_behaviour_ellipse_get_tilt:
|
|
* @self: a #ClutterBehaviourEllipse
|
|
* @angle_tilt_x: return location for tilt angle on the X axis, or %NULL.
|
|
* @angle_tilt_y: return location for tilt angle on the Y axis, or %NULL.
|
|
* @angle_tilt_z: return location for tilt angle on the Z axis, or %NULL.
|
|
*
|
|
* Gets the tilt of the ellipse around the center in Y axis.
|
|
*
|
|
* Since: 0.4
|
|
*/
|
|
void
|
|
clutter_behaviour_ellipse_get_tilt (ClutterBehaviourEllipse *self,
|
|
gdouble *angle_tilt_x,
|
|
gdouble *angle_tilt_y,
|
|
gdouble *angle_tilt_z)
|
|
{
|
|
ClutterBehaviourEllipsePrivate *priv;
|
|
|
|
g_return_if_fail (CLUTTER_IS_BEHAVIOUR_ELLIPSE (self));
|
|
|
|
priv = self->priv;
|
|
|
|
if (angle_tilt_x)
|
|
*angle_tilt_x = priv->angle_tilt_x;
|
|
|
|
if (angle_tilt_y)
|
|
*angle_tilt_y = priv->angle_tilt_y;
|
|
|
|
if (angle_tilt_z)
|
|
*angle_tilt_z = priv->angle_tilt_z;
|
|
}
|
|
|
|
/**
|
|
* clutter_behaviour_ellipse_get_direction:
|
|
* @self: a #ClutterBehaviourEllipse
|
|
*
|
|
* Retrieves the #ClutterRotateDirection used by the ellipse behaviour.
|
|
*
|
|
* Return value: the rotation direction
|
|
*
|
|
* Since: 0.4
|
|
*/
|
|
ClutterRotateDirection
|
|
clutter_behaviour_ellipse_get_direction (ClutterBehaviourEllipse *self)
|
|
{
|
|
g_return_val_if_fail (CLUTTER_IS_BEHAVIOUR_ELLIPSE (self),
|
|
CLUTTER_ROTATE_CW);
|
|
|
|
return self->priv->direction;
|
|
}
|
|
|
|
/**
|
|
* clutter_behaviour_ellipse_set_direction:
|
|
* @self: a #ClutterBehaviourEllipse
|
|
* @direction: the rotation direction
|
|
*
|
|
* Sets the rotation direction used by the ellipse behaviour.
|
|
*
|
|
* Since: 0.4
|
|
*/
|
|
void
|
|
clutter_behaviour_ellipse_set_direction (ClutterBehaviourEllipse *self,
|
|
ClutterRotateDirection direction)
|
|
{
|
|
ClutterBehaviourEllipsePrivate *priv;
|
|
|
|
g_return_if_fail (CLUTTER_IS_BEHAVIOUR_ELLIPSE (self));
|
|
|
|
priv = self->priv;
|
|
|
|
if (priv->direction != direction)
|
|
{
|
|
priv->direction = direction;
|
|
|
|
g_object_notify (G_OBJECT (self), "direction");
|
|
}
|
|
}
|