mirror of
https://github.com/brl/mutter.git
synced 2024-12-24 20:12:06 +00:00
11775a16f0
* clutter/clutter-actor.[ch]: Use the right get_type() function name for ClutterVertex, and add the CLUTTER_TYPE_VERTEX macro.
2597 lines
63 KiB
C
2597 lines
63 KiB
C
/*
|
|
* Clutter.
|
|
*
|
|
* An OpenGL based 'interactive canvas' library.
|
|
*
|
|
* Authored By Matthew Allum <mallum@openedhand.com>
|
|
*
|
|
* Copyright (C) 2006 OpenedHand
|
|
*
|
|
* 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, write to the
|
|
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
|
* Boston, MA 02111-1307, USA.
|
|
*/
|
|
|
|
/**
|
|
* SECTION:clutter-actor
|
|
* @short_description: Base abstract class for all visual stage actors.
|
|
*
|
|
* #ClutterActor is a base abstract class for all visual elements on the
|
|
* stage. Every object that must appear on the main #ClutterStage must also
|
|
* be a #ClutterActor, either by using one of the classes provided by
|
|
* Clutter, or by implementing a new #ClutterActor subclass.
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
#include "clutter-actor.h"
|
|
#include "clutter-container.h"
|
|
#include "clutter-main.h"
|
|
#include "clutter-enum-types.h"
|
|
#include "clutter-marshal.h"
|
|
#include "clutter-private.h"
|
|
#include "clutter-debug.h"
|
|
#include "clutter-units.h"
|
|
#include "cogl.h"
|
|
|
|
G_DEFINE_ABSTRACT_TYPE (ClutterActor,
|
|
clutter_actor,
|
|
G_TYPE_INITIALLY_UNOWNED);
|
|
|
|
static guint32 __id = 0;
|
|
|
|
|
|
#define CLUTTER_ACTOR_GET_PRIVATE(obj) \
|
|
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), CLUTTER_TYPE_ACTOR, ClutterActorPrivate))
|
|
|
|
struct _ClutterActorPrivate
|
|
{
|
|
ClutterActorBox coords;
|
|
|
|
ClutterGeometry clip; /* FIXME: Should be Units */
|
|
guint has_clip : 1;
|
|
ClutterFixed rxang, ryang, rzang; /* Rotation*/
|
|
gint rzx, rzy, rxy, rxz, ryx, ryz; /* FIXME: Should be Units */
|
|
gint z;
|
|
guint8 opacity;
|
|
ClutterActor *parent_actor;
|
|
gchar *name;
|
|
ClutterFixed scale_x, scale_y;
|
|
guint32 id; /* Unique ID */
|
|
};
|
|
|
|
enum
|
|
{
|
|
PROP_0,
|
|
PROP_X,
|
|
PROP_Y,
|
|
PROP_WIDTH,
|
|
PROP_HEIGHT,
|
|
PROP_CLIP,
|
|
PROP_HAS_CLIP,
|
|
PROP_OPACITY,
|
|
PROP_NAME,
|
|
PROP_VISIBLE
|
|
};
|
|
|
|
enum
|
|
{
|
|
SHOW,
|
|
HIDE,
|
|
DESTROY,
|
|
PARENT_SET,
|
|
|
|
LAST_SIGNAL
|
|
};
|
|
|
|
static guint actor_signals[LAST_SIGNAL] = { 0, };
|
|
|
|
static gboolean
|
|
redraw_update_idle (gpointer data)
|
|
{
|
|
ClutterMainContext *ctx = CLUTTER_CONTEXT();
|
|
|
|
if (ctx->update_idle)
|
|
{
|
|
g_source_remove (ctx->update_idle);
|
|
ctx->update_idle = 0;
|
|
}
|
|
|
|
clutter_redraw ();
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
static void
|
|
clutter_actor_real_show (ClutterActor *self)
|
|
{
|
|
if (!CLUTTER_ACTOR_IS_VISIBLE (self))
|
|
{
|
|
if (!CLUTTER_ACTOR_IS_REALIZED (self))
|
|
clutter_actor_realize (self);
|
|
|
|
CLUTTER_ACTOR_SET_FLAGS (self, CLUTTER_ACTOR_MAPPED);
|
|
|
|
if (CLUTTER_ACTOR_IS_VISIBLE (self))
|
|
clutter_actor_queue_redraw (self);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* clutter_actor_show
|
|
* @self: A #ClutterActor
|
|
*
|
|
* Flags a clutter actor to be displayed. An actor not shown will not
|
|
* appear on the display.
|
|
**/
|
|
void
|
|
clutter_actor_show (ClutterActor *self)
|
|
{
|
|
if (!CLUTTER_ACTOR_IS_VISIBLE (self))
|
|
{
|
|
g_object_ref (self);
|
|
|
|
g_signal_emit (self, actor_signals[SHOW], 0);
|
|
g_object_notify (G_OBJECT (self), "visible");
|
|
|
|
g_object_unref (self);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* clutter_actor_show_all:
|
|
* @self: a #ClutterActor
|
|
*
|
|
* Recursively show an actor, and any child actor if @self has
|
|
* child actors.
|
|
*
|
|
* Since: 0.2
|
|
*/
|
|
void
|
|
clutter_actor_show_all (ClutterActor *self)
|
|
{
|
|
ClutterActorClass *klass;
|
|
|
|
g_return_if_fail (CLUTTER_IS_ACTOR (self));
|
|
|
|
klass = CLUTTER_ACTOR_GET_CLASS (self);
|
|
if (klass->show_all)
|
|
klass->show_all (self);
|
|
}
|
|
|
|
void
|
|
clutter_actor_real_hide (ClutterActor *self)
|
|
{
|
|
if (CLUTTER_ACTOR_IS_VISIBLE (self))
|
|
{
|
|
CLUTTER_ACTOR_UNSET_FLAGS (self, CLUTTER_ACTOR_MAPPED);
|
|
clutter_actor_queue_redraw (self);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* clutter_actor_hide
|
|
* @self: A #ClutterActor
|
|
*
|
|
* Flags a clutter actor to be hidden. An actor not shown will not
|
|
* appear on the display.
|
|
**/
|
|
void
|
|
clutter_actor_hide (ClutterActor *self)
|
|
{
|
|
if (CLUTTER_ACTOR_IS_VISIBLE (self))
|
|
{
|
|
g_object_ref (self);
|
|
|
|
g_signal_emit (self, actor_signals[HIDE], 0);
|
|
g_object_notify (G_OBJECT (self), "visible");
|
|
|
|
g_object_unref (self);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* clutter_actor_hide_all:
|
|
* @self: a #ClutterActor
|
|
*
|
|
* Recursively hides an actor, and any child actor if @self
|
|
* has child actors.
|
|
*
|
|
* Since: 0.2
|
|
*/
|
|
void
|
|
clutter_actor_hide_all (ClutterActor *self)
|
|
{
|
|
ClutterActorClass *klass;
|
|
|
|
g_return_if_fail (CLUTTER_IS_ACTOR (self));
|
|
|
|
klass = CLUTTER_ACTOR_GET_CLASS (self);
|
|
if (klass->hide_all)
|
|
klass->hide_all (self);
|
|
}
|
|
|
|
/**
|
|
* clutter_actor_realize
|
|
* @self: A #ClutterActor
|
|
*
|
|
* Creates any underlying graphics resources needed by the actor to be
|
|
* displayed.
|
|
**/
|
|
void
|
|
clutter_actor_realize (ClutterActor *self)
|
|
{
|
|
ClutterActorClass *klass;
|
|
|
|
if (CLUTTER_ACTOR_IS_REALIZED (self))
|
|
return;
|
|
|
|
CLUTTER_ACTOR_SET_FLAGS (self, CLUTTER_ACTOR_REALIZED);
|
|
|
|
klass = CLUTTER_ACTOR_GET_CLASS (self);
|
|
|
|
if (klass->realize)
|
|
(klass->realize) (self);
|
|
}
|
|
|
|
/**
|
|
* clutter_actor_unrealize
|
|
* @self: A #ClutterActor
|
|
*
|
|
* Frees up any underlying graphics resources needed by the actor to be
|
|
* displayed.
|
|
**/
|
|
void
|
|
clutter_actor_unrealize (ClutterActor *self)
|
|
{
|
|
ClutterActorClass *klass;
|
|
|
|
if (!CLUTTER_ACTOR_IS_REALIZED (self))
|
|
return;
|
|
|
|
CLUTTER_ACTOR_UNSET_FLAGS (self, CLUTTER_ACTOR_REALIZED);
|
|
|
|
klass = CLUTTER_ACTOR_GET_CLASS (self);
|
|
|
|
if (klass->unrealize)
|
|
(klass->unrealize) (self);
|
|
}
|
|
|
|
/**
|
|
* clutter_actor_pick:
|
|
* @self: A #ClutterActor
|
|
* @color: A #ClutterColor
|
|
*
|
|
* Renders a silhouette of the actor in supplied color.
|
|
*
|
|
* This function should not never be called directly by applications.
|
|
**/
|
|
void
|
|
clutter_actor_pick (ClutterActor *self,
|
|
const ClutterColor *color)
|
|
{
|
|
ClutterActorClass *klass;
|
|
|
|
klass = CLUTTER_ACTOR_GET_CLASS (self);
|
|
|
|
if (G_UNLIKELY(klass->pick))
|
|
{
|
|
/* Its pretty unlikely anything other than a container actor
|
|
* would need to supply its own pick method.
|
|
*/
|
|
(klass->pick) (self, color);
|
|
}
|
|
else
|
|
{
|
|
cogl_color (color);
|
|
cogl_rectangle (0,
|
|
0,
|
|
clutter_actor_get_width(self),
|
|
clutter_actor_get_height(self));
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Utility functions for manipulating transformation matrix
|
|
*
|
|
* Matrix: 4x4 of ClutterFixed
|
|
*/
|
|
#define M(m,row,col) (m)[col*4+row]
|
|
|
|
/* Transform point (x,y,z) by matrix */
|
|
static void
|
|
mtx_transform (ClutterFixed m[16],
|
|
ClutterFixed *x, ClutterFixed *y, ClutterFixed *z,
|
|
ClutterFixed *w)
|
|
{
|
|
ClutterFixed _x, _y, _z, _w;
|
|
_x = *x;
|
|
_y = *y;
|
|
_z = *z;
|
|
_w = *w;
|
|
|
|
/* We care lot about precission here, so have to use QMUL */
|
|
*x = CFX_QMUL (M (m,0,0), _x) + CFX_QMUL (M (m,0,1), _y) +
|
|
CFX_QMUL (M (m,0,2), _z) + CFX_QMUL (M (m,0,3), _w);
|
|
|
|
*y = CFX_QMUL (M (m,1,0), _x) + CFX_QMUL (M (m,1,1), _y) +
|
|
CFX_QMUL (M (m,1,2), _z) + CFX_QMUL (M (m,1,3), _w);
|
|
|
|
*z = CFX_QMUL (M (m,2,0), _x) + CFX_QMUL (M (m,2,1), _y) +
|
|
CFX_QMUL (M (m,2,2), _z) + CFX_QMUL (M (m,2,3), _w);
|
|
|
|
*w = CFX_QMUL (M (m,3,0), _x) + CFX_QMUL (M (m,3,1), _y) +
|
|
CFX_QMUL (M (m,3,2), _z) + CFX_QMUL (M (m,3,3), _w);
|
|
|
|
/* Specially for Matthew: was going to put a comment here, but could not
|
|
* think of anything at all to say ;)
|
|
*/
|
|
}
|
|
|
|
/* Applies the transforms associated with this actor and its ancestors,
|
|
* retrieves the resulting OpenGL modelview matrix, and uses the matrix
|
|
* to transform the supplied point
|
|
*/
|
|
static void
|
|
clutter_actor_transform_point (ClutterActor *actor,
|
|
ClutterUnit *x,
|
|
ClutterUnit *y,
|
|
ClutterUnit *z,
|
|
ClutterUnit *w)
|
|
{
|
|
ClutterFixed mtx[16];
|
|
ClutterActorPrivate *priv;
|
|
|
|
g_return_if_fail (CLUTTER_IS_ACTOR (actor));
|
|
|
|
priv = actor->priv;
|
|
|
|
cogl_push_matrix();
|
|
_clutter_actor_apply_modelview_transform_recursive (actor);
|
|
|
|
cogl_get_modelview_matrix (mtx);
|
|
|
|
mtx_transform (mtx, x, y, z, w);
|
|
|
|
cogl_pop_matrix();
|
|
}
|
|
|
|
/* Help macros to scale from OpenGL <-1,1> coordinates system to our
|
|
* X-window based <0,window-size> coordinates
|
|
*/
|
|
#define MTX_GL_SCALE_X(x,w,v1,v2) (CFX_MUL( \
|
|
((CFX_DIV (x,w) + CFX_ONE) >> 1), v1) \
|
|
+ v2)
|
|
|
|
#define MTX_GL_SCALE_Y(y,w,v1,v2) (v1 - CFX_MUL( \
|
|
((CFX_DIV (y,w) + CFX_ONE) >> 1), v1) \
|
|
+ v2)
|
|
|
|
#define MTX_GL_SCALE_Z(z,w,v1,v2) MTX_GL_SCALE_X(z,w,v1,v2)
|
|
|
|
/**
|
|
* clutter_actor_apply_transform_to_point:
|
|
* @self: A #ClutterActor
|
|
* @point: A point as #ClutterVertex
|
|
* @vertex: The translated #ClutterVertex
|
|
*
|
|
* Transforms point in coordinates relative to the actor
|
|
* into screen coordiances
|
|
*
|
|
* Since: 0.4
|
|
**/
|
|
void
|
|
clutter_actor_apply_transform_to_point (ClutterActor *self,
|
|
ClutterVertex *point,
|
|
ClutterVertex *vertex)
|
|
{
|
|
ClutterFixed mtx_p[16];
|
|
ClutterFixed v[4];
|
|
ClutterFixed w = CFX_ONE;
|
|
|
|
g_return_if_fail (CLUTTER_IS_ACTOR (self));
|
|
|
|
/* First we tranform the point using the OpenGL modelview matrix */
|
|
clutter_actor_transform_point (self, &point->x, &point->y, &point->z, &w);
|
|
|
|
cogl_get_projection_matrix (mtx_p);
|
|
cogl_get_viewport (v);
|
|
|
|
/* Now, transform it again with the projection matrix */
|
|
mtx_transform (mtx_p, &point->x, &point->y, &point->z, &w);
|
|
|
|
/* Finaly translate from OpenGL coords to window coords */
|
|
vertex->x = MTX_GL_SCALE_X(point->x,w,v[2],v[0]);
|
|
vertex->y = MTX_GL_SCALE_Y(point->y,w,v[3],v[1]);
|
|
vertex->z = MTX_GL_SCALE_Z(point->z,w,v[2],v[0]);
|
|
}
|
|
|
|
/* Recursively tranform supplied vertices with the tranform for the current
|
|
* actor and all its ancestors (like clutter_actor_transform_point() but
|
|
* for all the vertices in one go).
|
|
*/
|
|
static void
|
|
clutter_actor_transform_vertices (ClutterActor * self,
|
|
ClutterVertex verts[4],
|
|
ClutterFixed w[4])
|
|
{
|
|
ClutterFixed mtx[16];
|
|
ClutterFixed _x, _y, _z, _w;
|
|
ClutterActorPrivate *priv;
|
|
|
|
g_return_if_fail (CLUTTER_IS_ACTOR (self));
|
|
|
|
priv = self->priv;
|
|
|
|
cogl_push_matrix();
|
|
_clutter_actor_apply_modelview_transform_recursive (self);
|
|
|
|
cogl_get_modelview_matrix (mtx);
|
|
|
|
_x = 0;
|
|
_y = 0;
|
|
_z = 0;
|
|
_w = CFX_ONE;
|
|
|
|
mtx_transform (mtx, &_x, &_y, &_z, &_w);
|
|
|
|
verts[0].x = _x;
|
|
verts[0].y = _y;
|
|
verts[0].z = _z;
|
|
w[0] = _w;
|
|
|
|
_x = priv->coords.x2 - priv->coords.x1;
|
|
_y = 0;
|
|
_z = 0;
|
|
_w = CFX_ONE;
|
|
|
|
mtx_transform (mtx, &_x, &_y, &_z, &_w);
|
|
|
|
verts[1].x = _x;
|
|
verts[1].y = _y;
|
|
verts[1].z = _z;
|
|
w[1] = _w;
|
|
|
|
_x = 0;
|
|
_y = priv->coords.y2 - priv->coords.y1;
|
|
_z = 0;
|
|
_w = CFX_ONE;
|
|
|
|
mtx_transform (mtx, &_x, &_y, &_z, &_w);
|
|
|
|
verts[2].x = _x;
|
|
verts[2].y = _y;
|
|
verts[2].z = _z;
|
|
w[2] = _w;
|
|
|
|
_x = priv->coords.x2 - priv->coords.x1;
|
|
_y = priv->coords.y2 - priv->coords.y1;
|
|
_z = 0;
|
|
_w = CFX_ONE;
|
|
|
|
mtx_transform (mtx, &_x, &_y, &_z, &_w);
|
|
|
|
verts[3].x = _x;
|
|
verts[3].y = _y;
|
|
verts[3].z = _z;
|
|
w[3] = _w;
|
|
|
|
cogl_pop_matrix();
|
|
}
|
|
|
|
/**
|
|
* clutter_actor_get_vertices:
|
|
* @self: A #ClutterActor
|
|
* @verts: Pointer to a location of an array of 4 #ClutterVertex where to
|
|
* store the result.
|
|
*
|
|
* Calculates the tranformed screen coordinaces of the four corners of
|
|
* the actor; the returned vertices relate to the ClutterActoBox
|
|
* coordinances as follows:
|
|
*
|
|
* v[0] contains (x1, y1)
|
|
* v[1] contains (x2, y1)
|
|
* v[2] contains (x1, y2)
|
|
* v[3] contains (x2, y2)
|
|
*
|
|
* Since: 0.4
|
|
**/
|
|
void
|
|
clutter_actor_get_vertices (ClutterActor *self,
|
|
ClutterVertex verts[4])
|
|
{
|
|
ClutterFixed mtx_p[16];
|
|
ClutterFixed v[4];
|
|
ClutterFixed w[4];
|
|
ClutterActorPrivate *priv;
|
|
|
|
g_return_if_fail (CLUTTER_IS_ACTOR (self));
|
|
|
|
priv = self->priv;
|
|
|
|
clutter_actor_transform_vertices (self, verts, w);
|
|
|
|
cogl_get_projection_matrix (mtx_p);
|
|
cogl_get_viewport (v);
|
|
|
|
mtx_transform (mtx_p,
|
|
&verts[0].x,
|
|
&verts[0].y,
|
|
&verts[0].z,
|
|
&w[0]);
|
|
|
|
verts[0].x = MTX_GL_SCALE_X (verts[0].x, w[0], v[2], v[0]);
|
|
verts[0].y = MTX_GL_SCALE_Y (verts[0].y, w[0], v[3], v[1]);
|
|
verts[0].z = MTX_GL_SCALE_Z (verts[0].z, w[0], v[2], v[0]);
|
|
|
|
mtx_transform (mtx_p,
|
|
&verts[1].x,
|
|
&verts[1].y,
|
|
&verts[1].z,
|
|
&w[1]);
|
|
|
|
verts[1].x = MTX_GL_SCALE_X (verts[1].x, w[1], v[2], v[0]);
|
|
verts[1].y = MTX_GL_SCALE_Y (verts[1].y, w[1], v[3], v[1]);
|
|
verts[1].z = MTX_GL_SCALE_Z (verts[1].z, w[1], v[2], v[0]);
|
|
|
|
mtx_transform (mtx_p,
|
|
&verts[2].x,
|
|
&verts[2].y,
|
|
&verts[2].z,
|
|
&w[2]);
|
|
|
|
verts[2].x = MTX_GL_SCALE_X (verts[2].x, w[2], v[2], v[0]);
|
|
verts[2].y = MTX_GL_SCALE_Y (verts[2].y, w[2], v[3], v[1]);
|
|
verts[2].z = MTX_GL_SCALE_Z (verts[2].z, w[2], v[2], v[0]);
|
|
|
|
mtx_transform (mtx_p,
|
|
&verts[3].x,
|
|
&verts[3].y,
|
|
&verts[3].z,
|
|
&w[3]);
|
|
|
|
verts[3].x = MTX_GL_SCALE_X (verts[3].x, w[3], v[2], v[0]);
|
|
verts[3].y = MTX_GL_SCALE_Y (verts[3].y, w[3], v[3], v[1]);
|
|
verts[3].z = MTX_GL_SCALE_Z (verts[3].z, w[3], v[2], v[0]);
|
|
}
|
|
|
|
/* Applies the transforms associated with this actor to the
|
|
* OpenGL modelview matrix.
|
|
*
|
|
* This function does not push/pop matrix; it is the responsibility
|
|
* of the caller to do so as appropriate
|
|
*/
|
|
void
|
|
_clutter_actor_apply_modelview_transform (ClutterActor * self)
|
|
{
|
|
ClutterActorPrivate *priv = self->priv;
|
|
|
|
if (clutter_actor_get_parent (self) != NULL)
|
|
{
|
|
cogl_translate (CLUTTER_UNITS_TO_INT (priv->coords.x1),
|
|
CLUTTER_UNITS_TO_INT (priv->coords.y1),
|
|
0);
|
|
}
|
|
|
|
/*
|
|
* because the rotation involves translations, we must scale before
|
|
* applying the rotations (if we apply the scale after the rotations,
|
|
* the translations included in the rotation are not scaled and so the
|
|
* entire object will move on the screen as a result of rotating it).
|
|
*/
|
|
if (priv->scale_x != CFX_ONE ||
|
|
priv->scale_y != CFX_ONE)
|
|
{
|
|
cogl_scale (priv->scale_x, priv->scale_y);
|
|
}
|
|
|
|
if (priv->rzang)
|
|
{
|
|
cogl_translate (priv->rzx, priv->rzy, 0);
|
|
cogl_rotatex (priv->rzang, 0, 0, CFX_ONE);
|
|
cogl_translate (-priv->rzx, -priv->rzy, 0);
|
|
}
|
|
|
|
if (priv->ryang)
|
|
{
|
|
cogl_translate (priv->ryx, 0, priv->z + priv->ryz);
|
|
cogl_rotatex (priv->ryang, 0, CFX_ONE, 0);
|
|
cogl_translate (-priv->ryx, 0, -(priv->z + priv->ryz));
|
|
}
|
|
|
|
if (priv->rxang)
|
|
{
|
|
cogl_translate (0, priv->rxy, priv->z + priv->rxz);
|
|
cogl_rotatex (priv->rxang, CFX_ONE, 0, 0);
|
|
cogl_translate (0, -priv->rxy, -(priv->z - priv->rxz));
|
|
}
|
|
|
|
if (priv->z)
|
|
cogl_translate (0, 0, priv->z);
|
|
|
|
if (priv->has_clip)
|
|
cogl_clip_set (&(priv->clip));
|
|
}
|
|
|
|
/* Recursively applies the transforms associated with this actor and
|
|
* its ancestors to the OpenGL modelview matrix.
|
|
*
|
|
* This function does not push/pop matrix; it is the responsibility
|
|
* of the caller to do so as appropriate
|
|
*/
|
|
void
|
|
_clutter_actor_apply_modelview_transform_recursive (ClutterActor * self)
|
|
{
|
|
ClutterActor * parent;
|
|
|
|
_clutter_actor_apply_modelview_transform (self);
|
|
|
|
parent = clutter_actor_get_parent (self);
|
|
|
|
if (parent)
|
|
_clutter_actor_apply_modelview_transform_recursive (parent);
|
|
}
|
|
|
|
/**
|
|
* clutter_actor_paint:
|
|
* @self: A #ClutterActor
|
|
*
|
|
* Renders the actor to display.
|
|
*
|
|
* This function should not be called directly by applications instead
|
|
* #clutter_actor_queue_redraw should be used to queue paints.
|
|
**/
|
|
void
|
|
clutter_actor_paint (ClutterActor *self)
|
|
{
|
|
ClutterActorPrivate *priv;
|
|
ClutterActorClass *klass;
|
|
ClutterMainContext *context;
|
|
g_return_if_fail (CLUTTER_IS_ACTOR (self));
|
|
priv = self->priv;
|
|
|
|
if (!CLUTTER_ACTOR_IS_REALIZED (self))
|
|
{
|
|
CLUTTER_NOTE (PAINT, "Attempting realize via paint()");
|
|
clutter_actor_realize(self);
|
|
|
|
if (!CLUTTER_ACTOR_IS_REALIZED (self))
|
|
{
|
|
CLUTTER_NOTE (PAINT, "Attempt failed, aborting paint");
|
|
return;
|
|
}
|
|
}
|
|
|
|
context = clutter_context_get_default ();
|
|
klass = CLUTTER_ACTOR_GET_CLASS (self);
|
|
|
|
cogl_push_matrix();
|
|
|
|
_clutter_actor_apply_modelview_transform (self);
|
|
|
|
if (G_UNLIKELY(context->pick_mode == TRUE))
|
|
{
|
|
ClutterColor col;
|
|
guint32 id;
|
|
|
|
id = clutter_actor_get_id (self);
|
|
|
|
/* Encode the actor id into a color */
|
|
col.red = (id >> 16) & 0xff;
|
|
col.green = (id >> 8) & 0xff;
|
|
col.blue = id & 0xff;
|
|
col.alpha = 0xff;
|
|
|
|
/* Actor will then paint silhouette of itself in supplied color.
|
|
* See clutter_stage_get_actor_at_pos() for where picking is enabled.
|
|
*/
|
|
clutter_actor_pick (self, &col);
|
|
}
|
|
else
|
|
{
|
|
if (G_LIKELY(klass->paint))
|
|
(klass->paint) (self);
|
|
}
|
|
|
|
if (priv->has_clip)
|
|
cogl_clip_unset();
|
|
|
|
cogl_pop_matrix();
|
|
}
|
|
|
|
#undef M
|
|
|
|
/**
|
|
* clutter_actor_request_coords:
|
|
* @self: A #ClutterActor
|
|
* @box: A #ClutterActorBox with requested new co-ordinates in ClutterUnits
|
|
*
|
|
* Requests new untransformed co-ordinates for the #ClutterActor
|
|
* ralative to any parent.
|
|
*
|
|
* This function should not be called directly by applications instead
|
|
* the various position/geometry methods should be used.
|
|
**/
|
|
void
|
|
clutter_actor_request_coords (ClutterActor *self,
|
|
ClutterActorBox *box)
|
|
{
|
|
ClutterActorClass *klass;
|
|
gboolean x_change, y_change, width_change, height_change;
|
|
|
|
klass = CLUTTER_ACTOR_GET_CLASS (self);
|
|
|
|
if (klass->request_coords)
|
|
klass->request_coords (self, box);
|
|
|
|
x_change = (self->priv->coords.x1 != box->x1);
|
|
y_change = (self->priv->coords.y1 != box->y1);
|
|
width_change = ((self->priv->coords.x2 - self->priv->coords.x1) !=
|
|
(box->x2 - box->x1));
|
|
height_change = ((self->priv->coords.y2 - self->priv->coords.y1) !=
|
|
(box->y2 - box->y1));
|
|
|
|
if (x_change || y_change || width_change || height_change)
|
|
{
|
|
self->priv->coords.x1 = box->x1;
|
|
self->priv->coords.y1 = box->y1;
|
|
self->priv->coords.x2 = box->x2;
|
|
self->priv->coords.y2 = box->y2;
|
|
|
|
if (CLUTTER_ACTOR_IS_VISIBLE (self))
|
|
clutter_actor_queue_redraw (self);
|
|
|
|
g_object_ref (self);
|
|
g_object_freeze_notify (G_OBJECT (self));
|
|
|
|
if (x_change)
|
|
g_object_notify (G_OBJECT (self), "x");
|
|
|
|
if (y_change)
|
|
g_object_notify (G_OBJECT (self), "y");
|
|
|
|
if (width_change)
|
|
g_object_notify (G_OBJECT (self), "width");
|
|
|
|
if (height_change)
|
|
g_object_notify (G_OBJECT (self), "height");
|
|
|
|
g_object_thaw_notify (G_OBJECT (self));
|
|
g_object_unref (self);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* clutter_actor_query_coords:
|
|
* @self: A #ClutterActor
|
|
* @box: A location to store the actors #ClutterActorBox co-ordinates
|
|
*
|
|
* Requests the untransformed co-ordinates (in ClutterUnits) for the
|
|
* #ClutterActor relative to any parent.
|
|
*
|
|
* This function should not be called directly by applications instead
|
|
* the various position/geometry methods should be used.
|
|
**/
|
|
void
|
|
clutter_actor_query_coords (ClutterActor *self,
|
|
ClutterActorBox *box)
|
|
{
|
|
ClutterActorClass *klass;
|
|
|
|
klass = CLUTTER_ACTOR_GET_CLASS (self);
|
|
|
|
box->x1 = self->priv->coords.x1;
|
|
box->y1 = self->priv->coords.y1;
|
|
box->x2 = self->priv->coords.x2;
|
|
box->y2 = self->priv->coords.y2;
|
|
|
|
if (klass->query_coords)
|
|
{
|
|
/* FIXME: This is kind of a cludge - we pass out *private*
|
|
* co-ords down to any subclasses so they can modify
|
|
* we then resync any changes. Needed for group class.
|
|
* Need to figure out nicer way.
|
|
*/
|
|
klass->query_coords(self, box);
|
|
|
|
self->priv->coords.x1 = box->x1;
|
|
self->priv->coords.y1 = box->y1;
|
|
self->priv->coords.x2 = box->x2;
|
|
self->priv->coords.y2 = box->y2;
|
|
}
|
|
}
|
|
|
|
static void
|
|
clutter_actor_set_property (GObject *object,
|
|
guint prop_id,
|
|
const GValue *value,
|
|
GParamSpec *pspec)
|
|
{
|
|
|
|
ClutterActor *actor;
|
|
ClutterActorPrivate *priv;
|
|
|
|
actor = CLUTTER_ACTOR(object);
|
|
priv = actor->priv;
|
|
|
|
switch (prop_id)
|
|
{
|
|
case PROP_X:
|
|
clutter_actor_set_position (actor,
|
|
g_value_get_int (value),
|
|
clutter_actor_get_y (actor));
|
|
break;
|
|
case PROP_Y:
|
|
clutter_actor_set_position (actor,
|
|
clutter_actor_get_x (actor),
|
|
g_value_get_int (value));
|
|
break;
|
|
case PROP_WIDTH:
|
|
clutter_actor_set_size (actor,
|
|
g_value_get_int (value),
|
|
clutter_actor_get_height (actor));
|
|
break;
|
|
case PROP_HEIGHT:
|
|
clutter_actor_set_size (actor,
|
|
clutter_actor_get_width (actor),
|
|
g_value_get_int (value));
|
|
break;
|
|
case PROP_OPACITY:
|
|
clutter_actor_set_opacity (actor, g_value_get_uchar (value));
|
|
break;
|
|
case PROP_NAME:
|
|
clutter_actor_set_name (actor, g_value_get_string (value));
|
|
break;
|
|
case PROP_VISIBLE:
|
|
if (g_value_get_boolean (value) == TRUE)
|
|
clutter_actor_show (actor);
|
|
else
|
|
clutter_actor_hide (actor);
|
|
break;
|
|
case PROP_CLIP:
|
|
{
|
|
ClutterGeometry *geom = g_value_get_boxed (value);
|
|
|
|
clutter_actor_set_clip (actor,
|
|
geom->x, geom->y,
|
|
geom->width, geom->height);
|
|
}
|
|
break;
|
|
default:
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void
|
|
clutter_actor_get_property (GObject *object,
|
|
guint prop_id,
|
|
GValue *value,
|
|
GParamSpec *pspec)
|
|
{
|
|
ClutterActor *actor;
|
|
ClutterActorPrivate *priv;
|
|
|
|
actor = CLUTTER_ACTOR(object);
|
|
priv = actor->priv;
|
|
|
|
switch (prop_id)
|
|
{
|
|
case PROP_X:
|
|
g_value_set_int (value, clutter_actor_get_x (actor));
|
|
break;
|
|
case PROP_Y:
|
|
g_value_set_int (value, clutter_actor_get_y (actor));
|
|
break;
|
|
case PROP_WIDTH:
|
|
g_value_set_int (value, clutter_actor_get_width (actor));
|
|
break;
|
|
case PROP_HEIGHT:
|
|
g_value_set_int (value, clutter_actor_get_height (actor));
|
|
break;
|
|
case PROP_OPACITY:
|
|
g_value_set_uchar (value, priv->opacity);
|
|
break;
|
|
case PROP_NAME:
|
|
g_value_set_string (value, priv->name);
|
|
break;
|
|
case PROP_VISIBLE:
|
|
g_value_set_boolean (value,
|
|
(CLUTTER_ACTOR_IS_VISIBLE (actor) != FALSE));
|
|
break;
|
|
case PROP_HAS_CLIP:
|
|
g_value_set_boolean (value, priv->has_clip);
|
|
break;
|
|
case PROP_CLIP:
|
|
g_value_set_boxed (value, &(priv->clip));
|
|
break;
|
|
default:
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void
|
|
clutter_actor_dispose (GObject *object)
|
|
{
|
|
ClutterActor *self = CLUTTER_ACTOR (object);
|
|
|
|
CLUTTER_NOTE (MISC, "Disposing of object (id=%d) of type `%s'",
|
|
self->priv->id,
|
|
g_type_name (G_OBJECT_TYPE (self)));
|
|
|
|
if (!(CLUTTER_PRIVATE_FLAGS (self) & CLUTTER_ACTOR_IN_DESTRUCTION))
|
|
{
|
|
CLUTTER_SET_PRIVATE_FLAGS (self, CLUTTER_ACTOR_IN_DESTRUCTION);
|
|
|
|
g_signal_emit (self, actor_signals[DESTROY], 0);
|
|
|
|
CLUTTER_UNSET_PRIVATE_FLAGS (self, CLUTTER_ACTOR_IN_DESTRUCTION);
|
|
}
|
|
|
|
G_OBJECT_CLASS (clutter_actor_parent_class)->dispose (object);
|
|
}
|
|
|
|
static void
|
|
clutter_actor_finalize (GObject *object)
|
|
{
|
|
ClutterActor *actor = CLUTTER_ACTOR (object);
|
|
|
|
g_free (actor->priv->name);
|
|
|
|
G_OBJECT_CLASS (clutter_actor_parent_class)->finalize (object);
|
|
}
|
|
|
|
static void
|
|
clutter_actor_class_init (ClutterActorClass *klass)
|
|
{
|
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
|
|
|
object_class->set_property = clutter_actor_set_property;
|
|
object_class->get_property = clutter_actor_get_property;
|
|
object_class->dispose = clutter_actor_dispose;
|
|
object_class->finalize = clutter_actor_finalize;
|
|
|
|
g_type_class_add_private (klass, sizeof (ClutterActorPrivate));
|
|
|
|
/**
|
|
* ClutterActor:x:
|
|
*
|
|
* X coordinate of the actor.
|
|
*/
|
|
g_object_class_install_property (object_class,
|
|
PROP_X,
|
|
g_param_spec_int ("x",
|
|
"X co-ord",
|
|
"X co-ord of actor",
|
|
-G_MAXINT, G_MAXINT,
|
|
0,
|
|
CLUTTER_PARAM_READWRITE));
|
|
/**
|
|
* ClutterActor:y:
|
|
*
|
|
* Y coordinate of the actor.
|
|
*/
|
|
g_object_class_install_property (object_class,
|
|
PROP_Y,
|
|
g_param_spec_int ("y",
|
|
"Y co-ord",
|
|
"Y co-ord of actor",
|
|
-G_MAXINT, G_MAXINT,
|
|
0,
|
|
CLUTTER_PARAM_READWRITE));
|
|
/**
|
|
* ClutterActor:width:
|
|
*
|
|
* Width of the actor (in pixels).
|
|
*/
|
|
g_object_class_install_property (object_class,
|
|
PROP_WIDTH,
|
|
g_param_spec_int ("width",
|
|
"Width",
|
|
"Width of actor in pixels",
|
|
0, G_MAXINT,
|
|
0,
|
|
CLUTTER_PARAM_READWRITE));
|
|
/**
|
|
* ClutterActor:height:
|
|
*
|
|
* Height of the actor (in pixels).
|
|
*/
|
|
g_object_class_install_property (object_class,
|
|
PROP_HEIGHT,
|
|
g_param_spec_int ("height",
|
|
"Height",
|
|
"Height of actor in pixels",
|
|
0, G_MAXINT,
|
|
0,
|
|
CLUTTER_PARAM_READWRITE));
|
|
/**
|
|
* ClutterActor:opacity:
|
|
*
|
|
* Opacity of the actor.
|
|
*/
|
|
g_object_class_install_property (object_class,
|
|
PROP_OPACITY,
|
|
g_param_spec_uchar ("opacity",
|
|
"Opacity",
|
|
"Opacity of actor",
|
|
0, 0xff,
|
|
0xff,
|
|
G_PARAM_CONSTRUCT | CLUTTER_PARAM_READWRITE));
|
|
/**
|
|
* ClutterActor:visible:
|
|
*
|
|
* Whether the actor is visible or not.
|
|
*/
|
|
g_object_class_install_property (object_class,
|
|
PROP_VISIBLE,
|
|
g_param_spec_boolean ("visible",
|
|
"Visible",
|
|
"Whether the actor is visible or not",
|
|
FALSE,
|
|
CLUTTER_PARAM_READWRITE));
|
|
/**
|
|
* ClutterActor:has-clip:
|
|
*
|
|
* Whether the actor has the clip property set or not.
|
|
*/
|
|
g_object_class_install_property (object_class,
|
|
PROP_HAS_CLIP,
|
|
g_param_spec_boolean ("has-clip",
|
|
"Has Clip",
|
|
"Whether the actor has a clip set or not",
|
|
FALSE,
|
|
CLUTTER_PARAM_READABLE));
|
|
/**
|
|
* ClutterActor:clip:
|
|
*
|
|
* The clip region for the actor.
|
|
*/
|
|
g_object_class_install_property (object_class,
|
|
PROP_CLIP,
|
|
g_param_spec_boxed ("clip",
|
|
"Clip",
|
|
"The clip region for the actor",
|
|
CLUTTER_TYPE_GEOMETRY,
|
|
CLUTTER_PARAM_READWRITE));
|
|
/**
|
|
* ClutterActor:name:
|
|
*
|
|
* The name of the actor.
|
|
*
|
|
* Since: 0.2
|
|
*/
|
|
g_object_class_install_property (object_class,
|
|
PROP_NAME,
|
|
g_param_spec_string ("name",
|
|
"Name",
|
|
"Name of the actor",
|
|
NULL,
|
|
CLUTTER_PARAM_READWRITE));
|
|
|
|
/**
|
|
* ClutterActor::destroy:
|
|
* @actor: the object which received the signal
|
|
*
|
|
* The ::destroy signal is emitted when an actor is destroyed,
|
|
* either by direct invocation of clutter_actor_destroy() or
|
|
* when the #ClutterGroup that contains the actor is destroyed.
|
|
*
|
|
* Since: 0.2
|
|
*/
|
|
actor_signals[DESTROY] =
|
|
g_signal_new ("destroy",
|
|
G_TYPE_FROM_CLASS (object_class),
|
|
G_SIGNAL_RUN_CLEANUP | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS,
|
|
G_STRUCT_OFFSET (ClutterActorClass, destroy),
|
|
NULL, NULL,
|
|
clutter_marshal_VOID__VOID,
|
|
G_TYPE_NONE, 0);
|
|
/**
|
|
* ClutterActor::show:
|
|
* @actor: the object which received the signal
|
|
*
|
|
* The ::show signal is emitted when an actor becomes visible.
|
|
*
|
|
* Since: 0.2
|
|
*/
|
|
actor_signals[SHOW] =
|
|
g_signal_new ("show",
|
|
G_TYPE_FROM_CLASS (object_class),
|
|
G_SIGNAL_RUN_FIRST,
|
|
G_STRUCT_OFFSET (ClutterActorClass, show),
|
|
NULL, NULL,
|
|
clutter_marshal_VOID__VOID,
|
|
G_TYPE_NONE, 0);
|
|
/**
|
|
* ClutterActor::hide:
|
|
* @actor: the object which received the signal
|
|
*
|
|
* The ::hide signal is emitted when an actor is no longer visible.
|
|
*
|
|
* Since: 0.2
|
|
*/
|
|
actor_signals[HIDE] =
|
|
g_signal_new ("hide",
|
|
G_TYPE_FROM_CLASS (object_class),
|
|
G_SIGNAL_RUN_FIRST,
|
|
G_STRUCT_OFFSET (ClutterActorClass, hide),
|
|
NULL, NULL,
|
|
clutter_marshal_VOID__VOID,
|
|
G_TYPE_NONE, 0);
|
|
/**
|
|
* ClutterActor::parent-set:
|
|
* @actor: the object which received the signal
|
|
* @old_parent: the previous parent of the actor, or %NULL
|
|
*
|
|
* This signal is emitted when the parent of the actor changes.
|
|
*
|
|
* Since: 0.2
|
|
*/
|
|
actor_signals[PARENT_SET] =
|
|
g_signal_new ("parent-set",
|
|
G_TYPE_FROM_CLASS (object_class),
|
|
G_SIGNAL_RUN_LAST,
|
|
G_STRUCT_OFFSET (ClutterActorClass, parent_set),
|
|
NULL, NULL,
|
|
clutter_marshal_VOID__OBJECT,
|
|
G_TYPE_NONE, 1,
|
|
CLUTTER_TYPE_ACTOR);
|
|
|
|
klass->show = clutter_actor_real_show;
|
|
klass->show_all = clutter_actor_show;
|
|
klass->hide = clutter_actor_real_hide;
|
|
klass->hide_all = clutter_actor_hide;
|
|
}
|
|
|
|
static void
|
|
clutter_actor_init (ClutterActor *self)
|
|
{
|
|
self->priv = CLUTTER_ACTOR_GET_PRIVATE (self);
|
|
|
|
self->priv->parent_actor = NULL;
|
|
self->priv->has_clip = FALSE;
|
|
self->priv->opacity = 0xff;
|
|
self->priv->id = __id++;
|
|
self->priv->scale_x = CFX_ONE;
|
|
self->priv->scale_y = CFX_ONE;
|
|
|
|
clutter_actor_set_position (self, 0, 0);
|
|
clutter_actor_set_size (self, 0, 0);
|
|
}
|
|
|
|
/**
|
|
* clutter_actor_destroy:
|
|
* @self: a #ClutterActor
|
|
*
|
|
* Destroys an actor. When an actor is destroyed, it will break any
|
|
* references it holds to other objects. If the actor is inside a
|
|
* group, the actor will be removed from the group.
|
|
*
|
|
* When you destroy a group its children will be destroyed as well.
|
|
*/
|
|
void
|
|
clutter_actor_destroy (ClutterActor *self)
|
|
{
|
|
g_return_if_fail (CLUTTER_IS_ACTOR (self));
|
|
|
|
if (!(CLUTTER_PRIVATE_FLAGS (self) & CLUTTER_ACTOR_IN_DESTRUCTION))
|
|
g_object_run_dispose (G_OBJECT (self));
|
|
}
|
|
|
|
/**
|
|
* clutter_actor_queue_redraw:
|
|
* @self: A #ClutterActor
|
|
*
|
|
* Queues up a redraw of an actor and any children. The redraw occurs
|
|
* once the main loop becomes idle (after the current batch of events
|
|
* has been processed, roughly).
|
|
*
|
|
* Applications rarely need to call this as redraws are handled automatically
|
|
* by modification functions.
|
|
*/
|
|
void
|
|
clutter_actor_queue_redraw (ClutterActor *self)
|
|
{
|
|
ClutterMainContext *ctx = CLUTTER_CONTEXT();
|
|
|
|
if (!ctx->update_idle)
|
|
{
|
|
CLUTTER_TIMESTAMP (SCHEDULER,
|
|
"Adding ideler for actor: %p", self);
|
|
ctx->update_idle = g_idle_add_full (G_PRIORITY_DEFAULT + 10,
|
|
redraw_update_idle,
|
|
NULL, NULL);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* clutter_actor_set_geometry:
|
|
* @self: A #ClutterActor
|
|
* @geometry: A #ClutterGeometry
|
|
*
|
|
* Sets the actors untransformed geometry in pixels relative to any
|
|
* parent actor.
|
|
*/
|
|
void
|
|
clutter_actor_set_geometry (ClutterActor *self,
|
|
const ClutterGeometry *geometry)
|
|
{
|
|
ClutterActorBox box;
|
|
|
|
box.x1 = CLUTTER_UNITS_FROM_INT (geometry->x);
|
|
box.y1 = CLUTTER_UNITS_FROM_INT (geometry->y);
|
|
box.x2 = CLUTTER_UNITS_FROM_INT (geometry->x + geometry->width);
|
|
box.y2 = CLUTTER_UNITS_FROM_INT (geometry->y + geometry->height);
|
|
|
|
clutter_actor_request_coords (self, &box);
|
|
}
|
|
|
|
/**
|
|
* clutter_actor_get_geometry:
|
|
* @self: A #ClutterActor
|
|
* @geometry: A location to store actors #ClutterGeometry
|
|
*
|
|
* Gets the actors untransformed geometry in pixels relative to any
|
|
* parent actor.
|
|
*/
|
|
void
|
|
clutter_actor_get_geometry (ClutterActor *self,
|
|
ClutterGeometry *geometry)
|
|
{
|
|
ClutterActorBox box;
|
|
|
|
g_return_if_fail (CLUTTER_IS_ACTOR (self));
|
|
|
|
clutter_actor_query_coords (self, &box);
|
|
|
|
geometry->x = CLUTTER_UNITS_TO_INT (box.x1);
|
|
geometry->y = CLUTTER_UNITS_TO_INT (box.y1);
|
|
geometry->width = CLUTTER_UNITS_TO_INT (box.x2 - box.x1);
|
|
geometry->height = CLUTTER_UNITS_TO_INT (box.y2 - box.y1);
|
|
}
|
|
|
|
/**
|
|
* clutter_actor_get_coords:
|
|
* @self: A #ClutterActor
|
|
* @x1: A location to store actors left position if non NULL.
|
|
* @y1: A location to store actors top position if non NULL.
|
|
* @x2: A location to store actors right position if non NULL.
|
|
* @y2: A location to store actors bottom position if non NULL.
|
|
*
|
|
* Gets the actors untransformed bounding rectangle co-ordinates in pixels
|
|
* relative to any parent actor.
|
|
*/
|
|
void
|
|
clutter_actor_get_coords (ClutterActor *self,
|
|
gint *x1,
|
|
gint *y1,
|
|
gint *x2,
|
|
gint *y2)
|
|
{
|
|
ClutterActorBox box;
|
|
|
|
g_return_if_fail (CLUTTER_IS_ACTOR (self));
|
|
|
|
clutter_actor_query_coords (self, &box);
|
|
|
|
if (x1)
|
|
*x1 = CLUTTER_UNITS_TO_INT (box.x1);
|
|
|
|
if (y1)
|
|
*y1 = CLUTTER_UNITS_TO_INT (box.y1);
|
|
|
|
if (x2)
|
|
*x2 = CLUTTER_UNITS_TO_INT (box.x2);
|
|
|
|
if (y2)
|
|
*y2 = CLUTTER_UNITS_TO_INT (box.y2);
|
|
}
|
|
|
|
/**
|
|
* clutter_actor_set_position
|
|
* @self: A #ClutterActor
|
|
* @x: New left position of actor in pixels.
|
|
* @y: New top position of actor in pixels.
|
|
*
|
|
* Sets the actors position in pixels relative to any
|
|
* parent actor.
|
|
*/
|
|
void
|
|
clutter_actor_set_position (ClutterActor *self,
|
|
gint x,
|
|
gint y)
|
|
{
|
|
ClutterActorBox box;
|
|
|
|
g_return_if_fail (CLUTTER_IS_ACTOR (self));
|
|
|
|
clutter_actor_query_coords (self, &box);
|
|
|
|
box.x2 += (CLUTTER_UNITS_FROM_INT (x) - box.x1);
|
|
box.y2 += (CLUTTER_UNITS_FROM_INT (y) - box.y1);
|
|
|
|
box.x1 = CLUTTER_UNITS_FROM_INT (x);
|
|
box.y1 = CLUTTER_UNITS_FROM_INT (y);
|
|
|
|
clutter_actor_request_coords (self, &box);
|
|
}
|
|
|
|
/**
|
|
* clutter_actor_move_by
|
|
* @self: A #ClutterActor
|
|
* @dx: Distance to move Actor on X axis.
|
|
* @dy: Distance to move Actor on Y axis.
|
|
*
|
|
* Moves an actor by specified distance relative to
|
|
* current position in pixels.
|
|
*
|
|
* Since: 0.2
|
|
*/
|
|
void
|
|
clutter_actor_move_by (ClutterActor *self,
|
|
gint dx,
|
|
gint dy)
|
|
{
|
|
ClutterActorBox box;
|
|
gint32 dxu = CLUTTER_UNITS_FROM_INT (dx);
|
|
gint32 dyu = CLUTTER_UNITS_FROM_INT (dy);
|
|
|
|
g_return_if_fail (CLUTTER_IS_ACTOR (self));
|
|
|
|
clutter_actor_query_coords (self, &box);
|
|
|
|
box.x2 += dxu;
|
|
box.y2 += dyu;
|
|
box.x1 += dxu;
|
|
box.y1 += dyu;
|
|
|
|
clutter_actor_request_coords (self, &box);
|
|
}
|
|
|
|
/**
|
|
* clutter_actor_set_size
|
|
* @self: A #ClutterActor
|
|
* @width: New width of actor in pixels
|
|
* @height: New height of actor in pixels
|
|
*
|
|
* Sets the actors size in pixels.
|
|
*/
|
|
void
|
|
clutter_actor_set_size (ClutterActor *self,
|
|
gint width,
|
|
gint height)
|
|
{
|
|
ClutterActorBox box;
|
|
|
|
g_return_if_fail (CLUTTER_IS_ACTOR (self));
|
|
|
|
clutter_actor_query_coords (self, &box);
|
|
|
|
box.x2 = box.x1 + CLUTTER_UNITS_FROM_INT (width);
|
|
box.y2 = box.y1 + CLUTTER_UNITS_FROM_INT (height);
|
|
|
|
clutter_actor_request_coords (self, &box);
|
|
}
|
|
|
|
/**
|
|
* clutter_actor_get_size:
|
|
* @self: A #ClutterActor
|
|
* @width: Location to store width if non NULL.
|
|
* @height: Location to store height if non NULL.
|
|
*
|
|
* Gets the size of an actor in pixels ignoring any scaling factors.
|
|
*
|
|
* Since: 0.2
|
|
*/
|
|
void
|
|
clutter_actor_get_size (ClutterActor *self,
|
|
guint *width,
|
|
guint *height)
|
|
{
|
|
g_return_if_fail (CLUTTER_IS_ACTOR (self));
|
|
|
|
if (width)
|
|
*width = clutter_actor_get_width (self);
|
|
|
|
if (height)
|
|
*height = clutter_actor_get_height (self);
|
|
}
|
|
|
|
/*
|
|
* clutter_actor_get_abs_position_units
|
|
* @self: A #ClutterActor
|
|
* @x: Location to store x position if non NULL.
|
|
* @y: Location to store y position if non NULL.
|
|
*
|
|
* Gets the absolute position of an actor in clutter units relative
|
|
* to the stage.
|
|
*
|
|
* Since: 0.4
|
|
*/
|
|
static void
|
|
clutter_actor_get_abs_position_units (ClutterActor *self,
|
|
gint32 *x,
|
|
gint32 *y)
|
|
{
|
|
ClutterVertex v1;
|
|
ClutterVertex v2;
|
|
|
|
v1.x = v1.y = v1.z = 0;
|
|
clutter_actor_apply_transform_to_point (self, &v1, &v2);
|
|
|
|
*x = v2.x;
|
|
*y = v2.y;
|
|
}
|
|
|
|
/**
|
|
* clutter_actor_get_abs_position
|
|
* @self: A #ClutterActor
|
|
* @x: Location to store x position if non NULL.
|
|
* @y: Location to store y position if non NULL.
|
|
*
|
|
* Gets the absolute position of an actor in pixels relative
|
|
* to the stage.
|
|
*/
|
|
void
|
|
clutter_actor_get_abs_position (ClutterActor *self,
|
|
gint *x,
|
|
gint *y)
|
|
{
|
|
gint32 xu, yu;
|
|
clutter_actor_get_abs_position_units (self, &xu, &yu);
|
|
|
|
*x = CLUTTER_UNITS_TO_INT (xu);
|
|
*y = CLUTTER_UNITS_TO_INT (yu);
|
|
}
|
|
|
|
/*
|
|
* clutter_actor_get_abs_size_units:
|
|
* @self: A #ClutterActor
|
|
* @width: Location to store width if non NULL.
|
|
* @height: Location to store height if non NULL.
|
|
*
|
|
* Gets the absolute size of an actor in clutter units taking into account
|
|
* an scaling factors.
|
|
*
|
|
* Note: When the actor (or one of its ancestors) is rotated around the x or y
|
|
* axis, it no longer appears as on the stage as a rectangle, but as a generic
|
|
* quadrangle; in that case this function returns the size of the smallest
|
|
* rectangle that encapsulates the entire quad. Please note that in this case
|
|
* no assumptions can be made about the relative position of this envelope to
|
|
* the absolute position of the actor, as returned by
|
|
* clutter_actor_get_abs_position() - if you need this information, you need
|
|
* to use clutter_actor_get_vertices() to get the coords of the actual
|
|
* quadrangle.
|
|
*
|
|
* Since: 0.4
|
|
*/
|
|
static void
|
|
clutter_actor_get_abs_size_units (ClutterActor *self,
|
|
gint32 *width,
|
|
gint32 *height)
|
|
{
|
|
ClutterVertex v[4];
|
|
ClutterFixed x_min, x_max, y_min, y_max;
|
|
gint i;
|
|
|
|
clutter_actor_get_vertices (self, v);
|
|
|
|
x_min = x_max = v[0].x;
|
|
y_min = y_max = v[0].y;
|
|
|
|
for (i = 1; i < sizeof(v)/sizeof(v[0]); ++i)
|
|
{
|
|
if (v[i].x < x_min)
|
|
x_min = v[i].x;
|
|
|
|
if (v[i].x > x_max)
|
|
x_max = v[i].x;
|
|
|
|
if (v[i].y < y_min)
|
|
y_min = v[i].y;
|
|
|
|
if (v[i].y > y_max)
|
|
y_max = v[i].y;
|
|
}
|
|
|
|
*width = x_max - x_min;
|
|
*height = y_max - y_min;
|
|
}
|
|
|
|
/**
|
|
* clutter_actor_get_abs_size:
|
|
* @self: A #ClutterActor
|
|
* @width: Location to store width if non NULL.
|
|
* @height: Location to store height if non NULL.
|
|
*
|
|
* Gets the absolute size of an actor taking into account
|
|
* an scaling factors
|
|
*/
|
|
void
|
|
clutter_actor_get_abs_size (ClutterActor *self,
|
|
guint *width,
|
|
guint *height)
|
|
{
|
|
gint32 wu, hu;
|
|
clutter_actor_get_abs_size_units (self, &wu, &hu);
|
|
|
|
*width = CLUTTER_UNITS_TO_INT (wu);
|
|
*height = CLUTTER_UNITS_TO_INT (hu);
|
|
}
|
|
|
|
|
|
/**
|
|
* clutter_actor_get_width
|
|
* @self: A #ClutterActor
|
|
*
|
|
* Retrieves the actors width ignoring any scaling factors.
|
|
*
|
|
* Return value: The actor width in pixels
|
|
**/
|
|
guint
|
|
clutter_actor_get_width (ClutterActor *self)
|
|
{
|
|
ClutterActorBox box;
|
|
|
|
g_return_val_if_fail (CLUTTER_IS_ACTOR (self), 0);
|
|
|
|
clutter_actor_query_coords (self, &box);
|
|
|
|
return CLUTTER_UNITS_TO_INT (box.x2 - box.x1);
|
|
}
|
|
|
|
/**
|
|
* clutter_actor_get_height
|
|
* @self: A #ClutterActor
|
|
*
|
|
* Retrieves the actors height ignoring any scaling factors.
|
|
*
|
|
* Return value: The actor height in pixels
|
|
**/
|
|
guint
|
|
clutter_actor_get_height (ClutterActor *self)
|
|
{
|
|
ClutterActorBox box;
|
|
|
|
g_return_val_if_fail (CLUTTER_IS_ACTOR (self), 0);
|
|
|
|
clutter_actor_query_coords (self, &box);
|
|
|
|
return CLUTTER_UNITS_TO_INT (box.y2 - box.y1);
|
|
}
|
|
|
|
/**
|
|
* clutter_actor_set_width
|
|
* @self: A #ClutterActor
|
|
* @width: Requested new width for actor
|
|
*
|
|
* Requests a new width for actor
|
|
*
|
|
* since: 2.0
|
|
**/
|
|
void
|
|
clutter_actor_set_width (ClutterActor *self, guint width)
|
|
{
|
|
clutter_actor_set_size (self,
|
|
width,
|
|
clutter_actor_get_height (self));
|
|
}
|
|
|
|
/**
|
|
* clutter_actor_set_height
|
|
* @self: A #ClutterActor
|
|
* @height: Requested new height for actor
|
|
*
|
|
* Requests a new height for actor
|
|
*
|
|
* since: 2.0
|
|
**/
|
|
void
|
|
clutter_actor_set_height (ClutterActor *self, guint height)
|
|
{
|
|
clutter_actor_set_size (self,
|
|
clutter_actor_get_width (self),
|
|
height);
|
|
}
|
|
|
|
|
|
/**
|
|
* clutter_actor_get_x
|
|
* @self: A #ClutterActor
|
|
*
|
|
* Retrieves the actors x position relative to any parent.
|
|
*
|
|
* Return value: The actor x position in pixels ignoring any tranforms
|
|
* (i.e scaling, rotation).
|
|
**/
|
|
gint
|
|
clutter_actor_get_x (ClutterActor *self)
|
|
{
|
|
ClutterActorBox box;
|
|
|
|
g_return_val_if_fail (CLUTTER_IS_ACTOR (self), 0);
|
|
|
|
clutter_actor_query_coords (self, &box);
|
|
|
|
return CLUTTER_UNITS_TO_INT (box.x1);
|
|
}
|
|
|
|
/**
|
|
* clutter_actor_get_y:
|
|
* @self: A #ClutterActor
|
|
*
|
|
* Retrieves the actors y position relative to any parent.
|
|
*
|
|
* Return value: The actor y position in pixels ignoring any tranforms
|
|
* (i.e scaling, rotation).
|
|
**/
|
|
gint
|
|
clutter_actor_get_y (ClutterActor *self)
|
|
{
|
|
ClutterActorBox box;
|
|
|
|
g_return_val_if_fail (CLUTTER_IS_ACTOR (self), 0);
|
|
|
|
clutter_actor_query_coords (self, &box);
|
|
|
|
return CLUTTER_UNITS_TO_INT (box.y1);
|
|
}
|
|
|
|
/**
|
|
* clutter_actor_set_scalex:
|
|
* @self: A #ClutterActor
|
|
* @scale_x: #ClutterFixed factor to scale actor by horizontally.
|
|
* @scale_y: #ClutterFixed factor to scale actor by vertically.
|
|
*
|
|
* Scales an actor with fixed point parameters.
|
|
*/
|
|
void
|
|
clutter_actor_set_scalex (ClutterActor *self,
|
|
ClutterFixed scale_x,
|
|
ClutterFixed scale_y)
|
|
{
|
|
g_return_if_fail (CLUTTER_IS_ACTOR (self));
|
|
|
|
self->priv->scale_x = scale_x;
|
|
self->priv->scale_y = scale_y;
|
|
|
|
if (CLUTTER_ACTOR_IS_VISIBLE (self))
|
|
clutter_actor_queue_redraw (self);
|
|
}
|
|
|
|
/**
|
|
* clutter_actor_set_scale:
|
|
* @self: A #ClutterActor
|
|
* @scale_x: double factor to scale actor by horizontally.
|
|
* @scale_y: double factor to scale actor by vertically.
|
|
*
|
|
* Scales an actor with floating point parameters.
|
|
*
|
|
* Since: 0.2
|
|
*/
|
|
void
|
|
clutter_actor_set_scale (ClutterActor *self,
|
|
double scale_x,
|
|
double scale_y)
|
|
{
|
|
g_return_if_fail (CLUTTER_IS_ACTOR (self));
|
|
|
|
clutter_actor_set_scalex (self,
|
|
CLUTTER_FLOAT_TO_FIXED (scale_x),
|
|
CLUTTER_FLOAT_TO_FIXED (scale_y));
|
|
}
|
|
|
|
/**
|
|
* clutter_actor_get_scalex:
|
|
* @self: A #ClutterActor
|
|
* @scale_x: Location to store horizonal fixed scale factor if non NULL.
|
|
* @scale_y: Location to store vertical fixed scale factor if non NULL.
|
|
*
|
|
* Retrieves an actors scale in fixed point.
|
|
*
|
|
* Since: 0.2
|
|
*/
|
|
void
|
|
clutter_actor_get_scalex (ClutterActor *self,
|
|
ClutterFixed *scale_x,
|
|
ClutterFixed *scale_y)
|
|
{
|
|
if (scale_x)
|
|
*scale_x = self->priv->scale_x;
|
|
|
|
if (scale_y)
|
|
*scale_y = self->priv->scale_y;
|
|
}
|
|
|
|
/**
|
|
* clutter_actor_get_scale:
|
|
* @self: A #ClutterActor
|
|
* @scale_x: Location to store horizonal float scale factor if non NULL.
|
|
* @scale_y: Location to store vertical float scale factor if non NULL.
|
|
*
|
|
* Retrieves an actors scale in floating point.
|
|
*
|
|
* Since: 0.2
|
|
*/
|
|
void
|
|
clutter_actor_get_scale (ClutterActor *self,
|
|
gdouble *scale_x,
|
|
gdouble *scale_y)
|
|
{
|
|
if (scale_x)
|
|
*scale_x = CLUTTER_FIXED_TO_FLOAT (self->priv->scale_x);
|
|
|
|
if (scale_y)
|
|
*scale_y = CLUTTER_FIXED_TO_FLOAT (self->priv->scale_y);
|
|
}
|
|
|
|
/**
|
|
* clutter_actor_set_scale_with_gravity:
|
|
* @self: A #ClutterActor
|
|
* @scale_x: scaling factor for x axis
|
|
* @scale_y: scaling factor for y axis
|
|
* @gravity: #ClutterGravity to apply to scaling.
|
|
*
|
|
* Scales the actor by scale_x, scale_y taking into consideration the
|
|
* required gravity.
|
|
*
|
|
* Since: 0.4
|
|
*/
|
|
void
|
|
clutter_actor_set_scale_with_gravity (ClutterActor *self,
|
|
gfloat scale_x,
|
|
gfloat scale_y,
|
|
ClutterGravity gravity)
|
|
{
|
|
clutter_actor_set_scale_with_gravityx (self,
|
|
CLUTTER_FLOAT_TO_FIXED (scale_x),
|
|
CLUTTER_FLOAT_TO_FIXED (scale_y),
|
|
gravity);
|
|
}
|
|
|
|
/**
|
|
* clutter_actor_set_scale_with_gravityx:
|
|
* @self: A #ClutterActor
|
|
* @scale_x: #ClutterFixed scaling factor for x axis
|
|
* @scale_y: #ClutterFixed scaling factor for y axis
|
|
* @gravity: #ClutterGravity to apply to scaling.
|
|
*
|
|
* Scales the actor by scale_x, scale_y taking into consideration the
|
|
* required gravity.
|
|
*
|
|
* Since: 0.4
|
|
*/
|
|
void
|
|
clutter_actor_set_scale_with_gravityx (ClutterActor *self,
|
|
ClutterFixed scale_x,
|
|
ClutterFixed scale_y,
|
|
ClutterGravity gravity)
|
|
{
|
|
ClutterActorBox box;
|
|
ClutterFixed sw, sh, w, h, x, y;
|
|
ClutterFixed old_scale_x, old_scale_y;
|
|
|
|
clutter_actor_get_scalex (self, &old_scale_x, &old_scale_y);
|
|
clutter_actor_set_scalex (self, scale_x, scale_y);
|
|
|
|
if (gravity == CLUTTER_GRAVITY_NONE ||
|
|
gravity == CLUTTER_GRAVITY_NORTH_WEST)
|
|
return;
|
|
|
|
clutter_actor_query_coords (self, &box);
|
|
|
|
w = CFX_MUL (box.x2 - box.x1, old_scale_x);
|
|
h = CFX_MUL (box.y2 - box.y1, old_scale_y);
|
|
sw = CFX_MUL (box.x2 - box.x1, scale_x);
|
|
sh = CFX_MUL (box.y2 - box.y1, scale_y);
|
|
|
|
|
|
x = box.x1;
|
|
y = box.y1;
|
|
|
|
switch (gravity)
|
|
{
|
|
case CLUTTER_GRAVITY_NORTH:
|
|
x = x - ((sw - w) / 2);
|
|
break;
|
|
case CLUTTER_GRAVITY_NORTH_EAST:
|
|
x = x + w - sw;
|
|
break;
|
|
case CLUTTER_GRAVITY_EAST:
|
|
x = x + w - sw;
|
|
y = y - ((sh - h) / 2);
|
|
break;
|
|
case CLUTTER_GRAVITY_SOUTH_EAST:
|
|
x = x + w - sw;
|
|
y = y + h - sh;
|
|
break;
|
|
case CLUTTER_GRAVITY_SOUTH:
|
|
x = x - ((sw - w) / 2);
|
|
y = y + h - sh;
|
|
break;
|
|
case CLUTTER_GRAVITY_SOUTH_WEST:
|
|
y = y + h - sh;
|
|
break;
|
|
case CLUTTER_GRAVITY_WEST:
|
|
y = y - ((sh - h) / 2);
|
|
break;
|
|
case CLUTTER_GRAVITY_CENTER:
|
|
x = x - ((sw - w) / 2);
|
|
y = y - ((sh - h) / 2);
|
|
default:
|
|
break;
|
|
}
|
|
|
|
box.x2 += (x - box.x1);
|
|
box.y2 += (y - box.y1);
|
|
box.x1 = x;
|
|
box.y1 = y;
|
|
|
|
clutter_actor_request_coords (self, &box);
|
|
}
|
|
|
|
/**
|
|
* clutter_actor_set_opacity:
|
|
* @self: A #ClutterActor
|
|
* @opacity: New opacity value for actor.
|
|
*
|
|
* Sets the actors opacity, with zero being completely transparent.
|
|
*/
|
|
void
|
|
clutter_actor_set_opacity (ClutterActor *self,
|
|
guint8 opacity)
|
|
{
|
|
g_return_if_fail (CLUTTER_IS_ACTOR (self));
|
|
|
|
self->priv->opacity = opacity;
|
|
|
|
if (CLUTTER_ACTOR_IS_VISIBLE (self))
|
|
clutter_actor_queue_redraw (self);
|
|
}
|
|
|
|
/**
|
|
* clutter_actor_get_opacity:
|
|
* @self: A #ClutterActor
|
|
*
|
|
* Retrieves the actors opacity.
|
|
*
|
|
* Return value: The actor opacity value.
|
|
*/
|
|
guint8
|
|
clutter_actor_get_opacity (ClutterActor *self)
|
|
{
|
|
ClutterActor *parent;
|
|
|
|
g_return_val_if_fail (CLUTTER_IS_ACTOR (self), 0);
|
|
|
|
parent = self->priv->parent_actor;
|
|
|
|
/* Factor in the actual actors opacity with parents */
|
|
if (parent && clutter_actor_get_opacity (parent) != 0xff)
|
|
return (clutter_actor_get_opacity(parent) * self->priv->opacity) / 0xff;
|
|
|
|
return self->priv->opacity;
|
|
}
|
|
|
|
/**
|
|
* clutter_actor_set_name:
|
|
* @self: A #ClutterActor
|
|
* @name: Textual tag to apply to actor
|
|
*
|
|
* Sets a textual tag to the actor.
|
|
*/
|
|
void
|
|
clutter_actor_set_name (ClutterActor *self,
|
|
const gchar *name)
|
|
{
|
|
g_return_if_fail (CLUTTER_IS_ACTOR (self));
|
|
|
|
g_object_ref (self);
|
|
|
|
g_free (self->priv->name);
|
|
|
|
if (name && name[0] != '\0')
|
|
self->priv->name = g_strdup(name);
|
|
|
|
g_object_notify (G_OBJECT (self), "name");
|
|
g_object_unref (self);
|
|
}
|
|
|
|
/**
|
|
* clutter_actor_get_name:
|
|
* @self: A #ClutterActor
|
|
*
|
|
* Retrieves the name of @self.
|
|
*
|
|
* Return value: pointer to textual tag for the actor. The
|
|
* returned string is owned by the actor and should not
|
|
* be modified or freed.
|
|
*/
|
|
G_CONST_RETURN gchar *
|
|
clutter_actor_get_name (ClutterActor *self)
|
|
{
|
|
g_return_val_if_fail (CLUTTER_IS_ACTOR (self), NULL);
|
|
|
|
return self->priv->name;
|
|
}
|
|
|
|
/**
|
|
* clutter_actor_get_id:
|
|
* @self: A #ClutterActor
|
|
*
|
|
* Retrieves the unique id for @self.
|
|
*
|
|
* Return value: Globally unique value for object instance.
|
|
*/
|
|
guint32
|
|
clutter_actor_get_id (ClutterActor *self)
|
|
{
|
|
g_return_val_if_fail (CLUTTER_IS_ACTOR (self), 0);
|
|
|
|
return self->priv->id;
|
|
}
|
|
|
|
/**
|
|
* clutter_actor_set_depth:
|
|
* @self: a #ClutterActor
|
|
* @depth: Z co-ord
|
|
*
|
|
* Sets the Z co-ordinate of @self to @depth. The Units of which are dependant
|
|
* on the perspective setup.
|
|
*/
|
|
void
|
|
clutter_actor_set_depth (ClutterActor *self,
|
|
gint depth)
|
|
{
|
|
ClutterActorPrivate *priv;
|
|
|
|
g_return_if_fail (CLUTTER_IS_ACTOR (self));
|
|
|
|
priv = self->priv;
|
|
|
|
/* Sets Z value. - FIXME: should invert ?*/
|
|
priv->z = depth;
|
|
|
|
if (priv->parent_actor && CLUTTER_IS_GROUP (priv->parent_actor))
|
|
{
|
|
/* We need to resort the group stacking order as to
|
|
* correctly render alpha values.
|
|
*
|
|
* FIXME: This is sub optimal. maybe queue the the sort
|
|
* before stacking
|
|
*/
|
|
clutter_group_sort_depth_order (CLUTTER_GROUP (priv->parent_actor));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* clutter_actor_get_depth:
|
|
* @self: a #ClutterActor
|
|
*
|
|
* Retrieves the depth of @self.
|
|
*
|
|
* Return value: the depth of a #ClutterActor
|
|
*/
|
|
gint
|
|
clutter_actor_get_depth (ClutterActor *self)
|
|
{
|
|
g_return_val_if_fail (CLUTTER_IS_ACTOR (self), -1);
|
|
|
|
return self->priv->z;
|
|
}
|
|
|
|
/**
|
|
* clutter_actor_rotate_z:
|
|
* @self: A #ClutterActor
|
|
* @angle: Angle of rotation
|
|
* @x: X co-ord to rotate actor around ( relative to actor position )
|
|
* @y: Y co-ord to rotate actor around ( relative to actor position )
|
|
*
|
|
* Rotates actor around the Z axis.
|
|
*/
|
|
void
|
|
clutter_actor_rotate_z (ClutterActor *self,
|
|
gfloat angle,
|
|
gint x,
|
|
gint y)
|
|
{
|
|
g_return_if_fail (CLUTTER_IS_ACTOR (self));
|
|
|
|
self->priv->rzang = CLUTTER_FLOAT_TO_FIXED (angle);
|
|
self->priv->rzx = x;
|
|
self->priv->rzy = y;
|
|
|
|
if (CLUTTER_ACTOR_IS_VISIBLE (self))
|
|
clutter_actor_queue_redraw (self);
|
|
}
|
|
|
|
/**
|
|
* clutter_actor_rotate_x:
|
|
* @self: A #ClutterActor
|
|
* @angle: Angle of rotation
|
|
* @y: Y co-ord to rotate actor around ( relative to actor position )
|
|
* @z: Z co-ord to rotate actor around ( relative to actor position )
|
|
*
|
|
* Rotates actor around the X axis.
|
|
*/
|
|
void
|
|
clutter_actor_rotate_x (ClutterActor *self,
|
|
gfloat angle,
|
|
gint y,
|
|
gint z)
|
|
{
|
|
g_return_if_fail (CLUTTER_IS_ACTOR (self));
|
|
|
|
self->priv->rxang = CLUTTER_FLOAT_TO_FIXED(angle);
|
|
self->priv->rxy = y;
|
|
self->priv->rxz = z;
|
|
|
|
if (CLUTTER_ACTOR_IS_VISIBLE (self))
|
|
clutter_actor_queue_redraw (self);
|
|
}
|
|
|
|
/**
|
|
* clutter_actor_rotate_y:
|
|
* @self: A #ClutterActor
|
|
* @angle: Angle of rotation
|
|
* @x: X co-ord to rotate actor around ( relative to actor position )
|
|
* @z: Z co-ord to rotate actor around ( relative to actor position )
|
|
*
|
|
* Rotates actor around the X axis.
|
|
*/
|
|
void
|
|
clutter_actor_rotate_y (ClutterActor *self,
|
|
gfloat angle,
|
|
gint x,
|
|
gint z)
|
|
{
|
|
g_return_if_fail (CLUTTER_IS_ACTOR (self));
|
|
|
|
self->priv->ryang = CLUTTER_FLOAT_TO_FIXED(angle);
|
|
|
|
self->priv->ryx = x;
|
|
self->priv->ryz = z;
|
|
|
|
if (CLUTTER_ACTOR_IS_VISIBLE (self))
|
|
clutter_actor_queue_redraw (self);
|
|
}
|
|
|
|
/**
|
|
* clutter_actor_rotate_zx:
|
|
* @self: A #ClutterActor
|
|
* @angle: Angle of rotation
|
|
* @x: X co-ord to rotate actor around ( relative to actor position )
|
|
* @y: Y co-ord to rotate actor around ( relative to actor position )
|
|
*
|
|
* Rotates actor around the Z axis.
|
|
*/
|
|
void
|
|
clutter_actor_rotate_zx (ClutterActor *self,
|
|
ClutterFixed angle,
|
|
gint x,
|
|
gint y)
|
|
{
|
|
g_return_if_fail (CLUTTER_IS_ACTOR (self));
|
|
|
|
self->priv->rzang = angle;
|
|
self->priv->rzx = x;
|
|
self->priv->rzy = y;
|
|
|
|
if (CLUTTER_ACTOR_IS_VISIBLE (self))
|
|
clutter_actor_queue_redraw (self);
|
|
}
|
|
|
|
/**
|
|
* clutter_actor_rotate_xx:
|
|
* @self: A #ClutterActor
|
|
* @angle: Angle of rotation
|
|
* @y: Y co-ord to rotate actor around ( relative to actor position )
|
|
* @z: Z co-ord to rotate actor around ( relative to actor position )
|
|
*
|
|
* Rotates actor around the X axis.
|
|
*/
|
|
void
|
|
clutter_actor_rotate_xx (ClutterActor *self,
|
|
ClutterFixed angle,
|
|
gint y,
|
|
gint z)
|
|
{
|
|
g_return_if_fail (CLUTTER_IS_ACTOR (self));
|
|
|
|
self->priv->rxang = angle;
|
|
self->priv->rxy = y;
|
|
self->priv->rxz = z;
|
|
|
|
if (CLUTTER_ACTOR_IS_VISIBLE (self))
|
|
clutter_actor_queue_redraw (self);
|
|
}
|
|
|
|
/**
|
|
* clutter_actor_rotate_yx:
|
|
* @self: A #ClutterActor
|
|
* @angle: Angle of rotation
|
|
* @x: X co-ord to rotate actor around ( relative to actor position )
|
|
* @z: Z co-ord to rotate actor around ( relative to actor position )
|
|
*
|
|
* Rotates actor around the X axis.
|
|
*/
|
|
void
|
|
clutter_actor_rotate_yx (ClutterActor *self,
|
|
ClutterFixed angle,
|
|
gint x,
|
|
gint z)
|
|
{
|
|
g_return_if_fail (CLUTTER_IS_ACTOR (self));
|
|
|
|
self->priv->ryang = angle;
|
|
self->priv->ryx = x;
|
|
self->priv->ryz = z;
|
|
|
|
if (CLUTTER_ACTOR_IS_VISIBLE (self))
|
|
clutter_actor_queue_redraw (self);
|
|
}
|
|
|
|
/**
|
|
* clutter_actor_get_rxangx:
|
|
* @self: A #ClutterActor
|
|
*
|
|
* Gets the angle of rotation around x axis in degrees.
|
|
*/
|
|
ClutterFixed
|
|
clutter_actor_get_rxangx (ClutterActor *self)
|
|
{
|
|
g_return_val_if_fail (CLUTTER_IS_ACTOR (self), 0);
|
|
return self->priv->rxang;
|
|
}
|
|
|
|
/**
|
|
* clutter_actor_get_ryangx:
|
|
* @self: A #ClutterActor
|
|
*
|
|
* Gets the angle of rotation around y axis in degrees.
|
|
*/
|
|
ClutterFixed
|
|
clutter_actor_get_ryangx (ClutterActor *self)
|
|
{
|
|
g_return_val_if_fail (CLUTTER_IS_ACTOR (self), 0);
|
|
return self->priv->ryang;
|
|
}
|
|
|
|
/**
|
|
* clutter_actor_get_rzangx:
|
|
* @self: A #ClutterActor
|
|
*
|
|
* Gets the angle of rotation around x axis in degrees.
|
|
*/
|
|
ClutterFixed
|
|
clutter_actor_get_rzangx (ClutterActor *self)
|
|
{
|
|
g_return_val_if_fail (CLUTTER_IS_ACTOR (self), 0);
|
|
return self->priv->rzang;
|
|
}
|
|
|
|
/**
|
|
* clutter_actor_set_clip:
|
|
* @self: A #ClutterActor
|
|
* @xoff: X offset of the clip rectangle
|
|
* @yoff: Y offset of the clip rectangle
|
|
* @width: Width of the clip rectangle
|
|
* @height: Height of the clip rectangle
|
|
*
|
|
* Sets clip area in pixels for @self.
|
|
*/
|
|
void
|
|
clutter_actor_set_clip (ClutterActor *self,
|
|
gint xoff,
|
|
gint yoff,
|
|
gint width,
|
|
gint height)
|
|
{
|
|
ClutterGeometry *clip;
|
|
|
|
g_return_if_fail (CLUTTER_IS_ACTOR (self));
|
|
|
|
clip = &(self->priv->clip);
|
|
|
|
clip->x = xoff;
|
|
clip->y = yoff;
|
|
clip->width = width;
|
|
clip->height = height;
|
|
|
|
self->priv->has_clip = TRUE;
|
|
|
|
g_object_notify (G_OBJECT (self), "has-clip");
|
|
g_object_notify (G_OBJECT (self), "clip");
|
|
}
|
|
|
|
/**
|
|
* clutter_actor_remove_clip
|
|
* @self: A #ClutterActor
|
|
*
|
|
* Removes clip area in pixels from @self.
|
|
*/
|
|
void
|
|
clutter_actor_remove_clip (ClutterActor *self)
|
|
{
|
|
g_return_if_fail (CLUTTER_IS_ACTOR (self));
|
|
|
|
self->priv->has_clip = FALSE;
|
|
|
|
g_object_notify (G_OBJECT (self), "has-clip");
|
|
}
|
|
|
|
/**
|
|
* clutter_actor_has_clip:
|
|
* @self: a #ClutterActor
|
|
*
|
|
* Gets whether the actor has a clip set or not.
|
|
*
|
|
* Return value: %TRUE if the actor has a clip set.
|
|
*
|
|
* Since: 0.1.1
|
|
*/
|
|
gboolean
|
|
clutter_actor_has_clip (ClutterActor *self)
|
|
{
|
|
g_return_val_if_fail (CLUTTER_IS_ACTOR (self), FALSE);
|
|
|
|
return self->priv->has_clip;
|
|
}
|
|
|
|
/**
|
|
* clutter_actor_set_parent:
|
|
* @self: A #ClutterActor
|
|
* @parent: A new #ClutterActor parent
|
|
*
|
|
* Sets the parent of @self to @parent. The opposite function is
|
|
* clutter_actor_unparent().
|
|
*
|
|
* This function should not be used by applications but by custom
|
|
* 'composite' actor sub classes.
|
|
*/
|
|
void
|
|
clutter_actor_set_parent (ClutterActor *self,
|
|
ClutterActor *parent)
|
|
{
|
|
g_return_if_fail (CLUTTER_IS_ACTOR (self));
|
|
g_return_if_fail (CLUTTER_IS_ACTOR (parent));
|
|
g_return_if_fail (self != parent);
|
|
|
|
if (self->priv->parent_actor != NULL)
|
|
{
|
|
g_warning ("Cannot set a parent on an actor which has a parent.\n"
|
|
"You must use clutter_actor_unparent() first.\n");
|
|
|
|
return;
|
|
}
|
|
|
|
if (CLUTTER_PRIVATE_FLAGS (self) & CLUTTER_ACTOR_IS_TOPLEVEL)
|
|
{
|
|
g_warning ("Cannot set a parent on a toplevel actor\n");
|
|
|
|
return;
|
|
}
|
|
|
|
g_object_ref_sink (self);
|
|
self->priv->parent_actor = parent;
|
|
g_signal_emit (self, actor_signals[PARENT_SET], 0, NULL);
|
|
|
|
if (CLUTTER_ACTOR_IS_REALIZED (self->priv->parent_actor))
|
|
clutter_actor_realize (self);
|
|
|
|
if (CLUTTER_ACTOR_IS_VISIBLE (self->priv->parent_actor) &&
|
|
CLUTTER_ACTOR_IS_VISIBLE (self))
|
|
{
|
|
clutter_actor_queue_redraw (self);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* clutter_actor_get_parent:
|
|
* @self: A #ClutterActor
|
|
*
|
|
* Retrieves the parent of @self.
|
|
*
|
|
* Return Value: The #ClutterActor parent or NULL
|
|
*/
|
|
ClutterActor *
|
|
clutter_actor_get_parent (ClutterActor *self)
|
|
{
|
|
g_return_val_if_fail (CLUTTER_IS_ACTOR (self), NULL);
|
|
|
|
return self->priv->parent_actor;
|
|
}
|
|
|
|
/**
|
|
* clutter_actor_unparent:
|
|
* @self: a #ClutterActor
|
|
*
|
|
* This function should not be used in applications. It should be called by
|
|
* implementations of group actors, to dissociate a child from the container.
|
|
*
|
|
* Since: 0.1.1
|
|
*/
|
|
void
|
|
clutter_actor_unparent (ClutterActor *self)
|
|
{
|
|
ClutterActor *old_parent;
|
|
|
|
g_return_if_fail (CLUTTER_IS_ACTOR (self));
|
|
|
|
if (self->priv->parent_actor == NULL)
|
|
return;
|
|
|
|
/* just hide the actor if we are reparenting it */
|
|
if (CLUTTER_ACTOR_IS_REALIZED (self))
|
|
{
|
|
if (CLUTTER_PRIVATE_FLAGS (self) & CLUTTER_ACTOR_IN_REPARENT)
|
|
clutter_actor_hide (self);
|
|
else
|
|
clutter_actor_unrealize (self);
|
|
}
|
|
|
|
old_parent = self->priv->parent_actor;
|
|
self->priv->parent_actor = NULL;
|
|
g_signal_emit (self, actor_signals[PARENT_SET], 0, old_parent);
|
|
|
|
g_object_unref (self);
|
|
}
|
|
|
|
/**
|
|
* clutter_actor_reparent:
|
|
* @self: a #ClutterActor
|
|
* @new_parent: the new #ClutterActor parent
|
|
*
|
|
* This function resets the parent actor of @self. It is
|
|
* logically equivalent to calling clutter_actory_unparent()
|
|
* and clutter_actor_set_parent().
|
|
*
|
|
* Since: 0.2
|
|
*/
|
|
void
|
|
clutter_actor_reparent (ClutterActor *self,
|
|
ClutterActor *new_parent)
|
|
{
|
|
ClutterActorPrivate *priv;
|
|
|
|
g_return_if_fail (CLUTTER_IS_ACTOR (self));
|
|
g_return_if_fail (CLUTTER_IS_ACTOR (new_parent));
|
|
g_return_if_fail (self != new_parent);
|
|
|
|
if (CLUTTER_PRIVATE_FLAGS (self) & CLUTTER_ACTOR_IS_TOPLEVEL)
|
|
{
|
|
g_warning ("Cannot set a parent on a toplevel actor\n");
|
|
return;
|
|
}
|
|
|
|
priv = self->priv;
|
|
|
|
if (priv->parent_actor != new_parent)
|
|
{
|
|
ClutterActor *old_parent;
|
|
|
|
/* if the actor and the parent have already been realized,
|
|
* mark the actor as reparenting, so that clutter_actor_unparent()
|
|
* just hides the actor instead of unrealize it.
|
|
*/
|
|
if (CLUTTER_ACTOR_IS_REALIZED (self) &&
|
|
CLUTTER_ACTOR_IS_REALIZED (new_parent))
|
|
{
|
|
CLUTTER_SET_PRIVATE_FLAGS (self, CLUTTER_ACTOR_IN_REPARENT);
|
|
}
|
|
|
|
old_parent = priv->parent_actor;
|
|
|
|
g_object_ref (self);
|
|
|
|
/* FIXME: below assumes only containers can reparent */
|
|
clutter_container_remove_actor (CLUTTER_CONTAINER (priv->parent_actor),
|
|
self);
|
|
clutter_container_add_actor (CLUTTER_CONTAINER (new_parent), self);
|
|
|
|
g_object_unref (self);
|
|
|
|
if (CLUTTER_PRIVATE_FLAGS (self) & CLUTTER_ACTOR_IN_REPARENT)
|
|
{
|
|
CLUTTER_UNSET_PRIVATE_FLAGS (self, CLUTTER_ACTOR_IN_REPARENT);
|
|
|
|
clutter_actor_queue_redraw (self);
|
|
}
|
|
}
|
|
}
|
|
/**
|
|
* clutter_actor_raise:
|
|
* @self: A #ClutterActor
|
|
* @below: A #ClutterActor to raise above.
|
|
*
|
|
* Puts @self above @below.
|
|
* Both actors must have the same parent.
|
|
*/
|
|
void
|
|
clutter_actor_raise (ClutterActor *self,
|
|
ClutterActor *below)
|
|
{
|
|
ClutterActor *parent;
|
|
|
|
g_return_if_fail (CLUTTER_IS_ACTOR (self));
|
|
|
|
parent = clutter_actor_get_parent (self);
|
|
if (!parent)
|
|
{
|
|
g_warning ("Actor of type %s is not inside a group",
|
|
g_type_name (G_OBJECT_TYPE (self)));
|
|
return;
|
|
}
|
|
|
|
if (below)
|
|
{
|
|
if (parent != clutter_actor_get_parent (below))
|
|
{
|
|
g_warning ("Actor of type %s is not in the same "
|
|
"group of actor of type %s",
|
|
g_type_name (G_OBJECT_TYPE (self)),
|
|
g_type_name (G_OBJECT_TYPE (below)));
|
|
return;
|
|
}
|
|
}
|
|
|
|
clutter_group_raise (CLUTTER_GROUP (parent), self, below);
|
|
}
|
|
|
|
/**
|
|
* clutter_actor_lower:
|
|
* @self: A #ClutterActor
|
|
* @above: A #ClutterActor to lower below
|
|
*
|
|
* Puts @self below @above.
|
|
* Both actors must have the same parent.
|
|
*/
|
|
void
|
|
clutter_actor_lower (ClutterActor *self,
|
|
ClutterActor *above)
|
|
{
|
|
ClutterActor *parent;
|
|
|
|
g_return_if_fail (CLUTTER_IS_ACTOR(self));
|
|
|
|
parent = clutter_actor_get_parent (self);
|
|
if (!parent)
|
|
{
|
|
g_warning ("Actor of type %s is not inside a group",
|
|
g_type_name (G_OBJECT_TYPE (self)));
|
|
return;
|
|
}
|
|
|
|
if (above)
|
|
{
|
|
if (parent != clutter_actor_get_parent (above))
|
|
{
|
|
g_warning ("Actor of type %s is not in the same "
|
|
"group of actor of type %s",
|
|
g_type_name (G_OBJECT_TYPE (self)),
|
|
g_type_name (G_OBJECT_TYPE (above)));
|
|
return;
|
|
}
|
|
}
|
|
|
|
/* FIXME: group_lower should be an overidable method ? */
|
|
clutter_group_lower (CLUTTER_GROUP (parent), self, above);
|
|
}
|
|
|
|
/**
|
|
* clutter_actor_raise_top:
|
|
* @self: A #ClutterActor
|
|
*
|
|
* Raises @self to the top.
|
|
*/
|
|
void
|
|
clutter_actor_raise_top (ClutterActor *self)
|
|
{
|
|
clutter_actor_raise (self, NULL);
|
|
}
|
|
|
|
/**
|
|
* clutter_actor_lower_bottom:
|
|
* @self: A #ClutterActor
|
|
*
|
|
* Lowers @self to the bottom.
|
|
*/
|
|
void
|
|
clutter_actor_lower_bottom (ClutterActor *self)
|
|
{
|
|
clutter_actor_lower (self, NULL);
|
|
}
|
|
|
|
/*
|
|
* ClutterGemoetry
|
|
*/
|
|
|
|
static ClutterGeometry*
|
|
clutter_geometry_copy (const ClutterGeometry *geometry)
|
|
{
|
|
ClutterGeometry *result = g_new (ClutterGeometry, 1);
|
|
|
|
*result = *geometry;
|
|
|
|
return result;
|
|
}
|
|
|
|
GType
|
|
clutter_geometry_get_type (void)
|
|
{
|
|
static GType our_type = 0;
|
|
|
|
if (our_type == 0)
|
|
our_type = g_boxed_type_register_static (g_intern_static_string ("ClutterGeometry"),
|
|
(GBoxedCopyFunc) clutter_geometry_copy,
|
|
(GBoxedFreeFunc) g_free);
|
|
|
|
return our_type;
|
|
}
|
|
|
|
/*
|
|
* ClutterVertices
|
|
*/
|
|
|
|
static ClutterVertex *
|
|
clutter_vertex_copy (const ClutterVertex *vertex)
|
|
{
|
|
ClutterVertex *result = g_new (ClutterVertex, 1);
|
|
|
|
*result = *vertex;
|
|
|
|
return result;
|
|
}
|
|
|
|
GType
|
|
clutter_vertex_get_type (void)
|
|
{
|
|
static GType our_type = 0;
|
|
|
|
if (our_type == 0)
|
|
our_type = g_boxed_type_register_static (g_intern_static_string ("ClutterVertex"),
|
|
(GBoxedCopyFunc) clutter_vertex_copy,
|
|
(GBoxedFreeFunc) g_free);
|
|
|
|
return our_type;
|
|
}
|
|
|
|
/*
|
|
* ClutterActorBox
|
|
*/
|
|
static ClutterActorBox *
|
|
clutter_actor_box_copy (const ClutterActorBox *box)
|
|
{
|
|
ClutterActorBox *result = g_new (ClutterActorBox, 1);
|
|
|
|
*result = *box;
|
|
|
|
return result;
|
|
}
|
|
|
|
GType
|
|
clutter_actor_box_get_type (void)
|
|
{
|
|
static GType our_type = 0;
|
|
|
|
if (our_type == 0)
|
|
our_type = g_boxed_type_register_static (g_intern_static_string ("ClutterActorBox"),
|
|
(GBoxedCopyFunc) clutter_actor_box_copy,
|
|
(GBoxedFreeFunc) g_free);
|
|
return our_type;
|
|
}
|
|
|