mirror of
https://github.com/brl/mutter.git
synced 2024-11-23 00:20:42 -05:00
[actor] Allow changing the transformations matrix
Currently, the transformation matrix for an actor is constructed from scenegraph-related accessors. An actor, though, can call COGL API to add new transformations inside the paint() implementation, for instance: static void my_foo_paint (ClutterActor *a) { ... cogl_translate (-scroll_x, -scroll_y, 0); ... } Unfortunately these transformations will be completely ignored by the scenegraph machinery; for instance, getting the actor-relative coordinates from event coordinates is going to break badly because of this. In order to make the scenegraph aware of the potential of additional transformations, we need a ::apply_transform() virtual function. This vfunc will pass a CoglMatrix which can be used to apply additional operations: static void my_foo_apply_transform (ClutterActor *a, CoglMatrix *m) { CLUTTER_ACTOR_CLASS (my_foo_parent_class)->apply_transform (a, m); ... cogl_matrix_translate (m, -scroll_x, -scroll_y, 0); ... } The ::paint() implementation will be called with the actor already using the newly applied transformation matrix, as expected: static void my_foo_paint (ClutterActor *a) { ... } The ::apply_transform() implementations *must* chain up, so that the various transformations of each class are preserved. The default implementation inside ClutterActor applies all the transformations defined by the scenegraph-related accessors. Actors performing transformations inside the paint() function will continue to work as previously.
This commit is contained in:
parent
0414daf0fb
commit
37bd35f592
@ -497,12 +497,12 @@ static gboolean clutter_anchor_coord_is_zero (const AnchorCoord *coord);
|
||||
|
||||
/* Helper macro which translates by the anchor coord, applies the
|
||||
given transformation and then translates back */
|
||||
#define TRANSFORM_ABOUT_ANCHOR_COORD(actor,coord,transform) G_STMT_START { \
|
||||
#define TRANSFORM_ABOUT_ANCHOR_COORD(a,m,c,_transform) G_STMT_START { \
|
||||
gfloat _tx, _ty, _tz; \
|
||||
clutter_anchor_coord_get_units ((actor), (coord), &_tx, &_ty, &_tz); \
|
||||
cogl_translate (_tx, _ty, _tz); \
|
||||
{ transform; } \
|
||||
cogl_translate (-_tx, -_ty, -_tz); } G_STMT_END
|
||||
clutter_anchor_coord_get_units ((a), (c), &_tx, &_ty, &_tz); \
|
||||
cogl_matrix_translate ((m), _tx, _ty, _tz); \
|
||||
{ _transform; } \
|
||||
cogl_matrix_translate ((m), -_tx, -_ty, -_tz); } G_STMT_END
|
||||
|
||||
G_DEFINE_ABSTRACT_TYPE_WITH_CODE (ClutterActor,
|
||||
clutter_actor,
|
||||
@ -2119,25 +2119,23 @@ clutter_actor_get_abs_allocation_vertices (ClutterActor *self,
|
||||
verts);
|
||||
}
|
||||
|
||||
/* 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
|
||||
*/
|
||||
static void
|
||||
_clutter_actor_apply_modelview_transform (ClutterActor *self)
|
||||
clutter_actor_real_apply_transform (ClutterActor *self,
|
||||
CoglMatrix *matrix)
|
||||
{
|
||||
ClutterActorPrivate *priv = self->priv;
|
||||
gboolean is_stage = CLUTTER_IS_STAGE (self);
|
||||
|
||||
if (!is_stage)
|
||||
cogl_translate (priv->allocation.x1,
|
||||
{
|
||||
cogl_matrix_translate (matrix,
|
||||
priv->allocation.x1,
|
||||
priv->allocation.y1,
|
||||
0);
|
||||
0.0);
|
||||
}
|
||||
|
||||
if (priv->z)
|
||||
cogl_translate (0, 0, priv->z);
|
||||
cogl_matrix_translate (matrix, 0, 0, priv->z);
|
||||
|
||||
/*
|
||||
* because the rotation involves translations, we must scale before
|
||||
@ -2147,37 +2145,66 @@ _clutter_actor_apply_modelview_transform (ClutterActor *self)
|
||||
*/
|
||||
if (priv->scale_x != 1.0 || priv->scale_y != 1.0)
|
||||
{
|
||||
TRANSFORM_ABOUT_ANCHOR_COORD (self,
|
||||
TRANSFORM_ABOUT_ANCHOR_COORD (self, matrix,
|
||||
&priv->scale_center,
|
||||
cogl_scale (priv->scale_x,
|
||||
cogl_matrix_scale (matrix,
|
||||
priv->scale_x,
|
||||
priv->scale_y,
|
||||
1.0));
|
||||
}
|
||||
|
||||
if (priv->rzang)
|
||||
TRANSFORM_ABOUT_ANCHOR_COORD (self,
|
||||
TRANSFORM_ABOUT_ANCHOR_COORD (self, matrix,
|
||||
&priv->rz_center,
|
||||
cogl_rotate (priv->rzang, 0, 0, 1.0));
|
||||
cogl_matrix_rotate (matrix,
|
||||
priv->rzang,
|
||||
0, 0, 1.0));
|
||||
|
||||
if (priv->ryang)
|
||||
TRANSFORM_ABOUT_ANCHOR_COORD (self,
|
||||
TRANSFORM_ABOUT_ANCHOR_COORD (self, matrix,
|
||||
&priv->ry_center,
|
||||
cogl_rotate (priv->ryang, 0, 1.0, 0));
|
||||
cogl_matrix_rotate (matrix,
|
||||
priv->ryang,
|
||||
0, 1.0, 0));
|
||||
|
||||
if (priv->rxang)
|
||||
TRANSFORM_ABOUT_ANCHOR_COORD (self,
|
||||
TRANSFORM_ABOUT_ANCHOR_COORD (self, matrix,
|
||||
&priv->rx_center,
|
||||
cogl_rotate (priv->rxang, 1.0, 0, 0));
|
||||
cogl_matrix_rotate (matrix,
|
||||
priv->rxang,
|
||||
1.0, 0, 0));
|
||||
|
||||
if (!is_stage && !clutter_anchor_coord_is_zero (&priv->anchor))
|
||||
{
|
||||
gfloat x, y, z;
|
||||
|
||||
clutter_anchor_coord_get_units (self, &priv->anchor, &x, &y, &z);
|
||||
cogl_translate (-x, -y, -z);
|
||||
cogl_matrix_translate (matrix, -x, -y, -z);
|
||||
}
|
||||
}
|
||||
|
||||
/* 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
|
||||
*/
|
||||
static void
|
||||
_clutter_actor_apply_modelview_transform (ClutterActor *self)
|
||||
{
|
||||
CoglMatrix matrix, cur, new;
|
||||
|
||||
cogl_matrix_init_identity (&matrix);
|
||||
|
||||
clutter_actor_get_transformation_matrix (self, &matrix);
|
||||
|
||||
cogl_get_modelview_matrix (&cur);
|
||||
|
||||
cogl_matrix_multiply (&new, &cur, &matrix);
|
||||
|
||||
cogl_set_modelview_matrix (&new);
|
||||
}
|
||||
|
||||
/* Recursively applies the transforms associated with this actor and
|
||||
* its ancestors to the OpenGL modelview matrix. Use NULL if you want this
|
||||
* to go all the way down to the stage.
|
||||
@ -4229,6 +4256,7 @@ clutter_actor_class_init (ClutterActorClass *klass)
|
||||
klass->get_preferred_height = clutter_actor_real_get_preferred_height;
|
||||
klass->allocate = clutter_actor_real_allocate;
|
||||
klass->queue_redraw = clutter_actor_real_queue_redraw;
|
||||
klass->apply_transform = clutter_actor_real_apply_transform;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -9163,3 +9191,21 @@ clutter_actor_unset_flags (ClutterActor *self,
|
||||
|
||||
g_object_thaw_notify (obj);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_actor_get_transformation_matrix:
|
||||
* @self: a #ClutterActor
|
||||
* @matrix: (out): the return location for a #CoglMatrix
|
||||
*
|
||||
* Retrieves the transformations applied to @self
|
||||
*
|
||||
* Since: 1.0
|
||||
*/
|
||||
void
|
||||
clutter_actor_get_transformation_matrix (ClutterActor *self,
|
||||
CoglMatrix *matrix)
|
||||
{
|
||||
g_return_if_fail (CLUTTER_IS_ACTOR (self));
|
||||
|
||||
CLUTTER_ACTOR_GET_CLASS (self)->apply_transform (self, matrix);
|
||||
}
|
||||
|
@ -178,7 +178,11 @@ struct _ClutterActor
|
||||
* and natural heights of an actor for a given width; it is used by
|
||||
* clutter_actor_get_preferred_height()
|
||||
* @allocate: virtual function, used when settings the coordinates of an
|
||||
* actor; it is used by clutter_actor_allocate()
|
||||
* actor; it is used by clutter_actor_allocate(); it must chain up to
|
||||
* the parent's implementation
|
||||
* @apply_transform: virtual function, used when applying the transformations
|
||||
* to an actor before painting it or when transforming coordinates or
|
||||
* the allocation; it must chain up to the parent's implementation
|
||||
* @parent_set: signal class handler for the #ClutterActor::parent-set
|
||||
* @destroy: signal class handler for #ClutterActor::destroy
|
||||
* @pick: virtual function, used to draw an outline of the actor with
|
||||
@ -238,6 +242,11 @@ struct _ClutterActorClass
|
||||
void (* allocate) (ClutterActor *actor,
|
||||
const ClutterActorBox *box,
|
||||
ClutterAllocationFlags flags);
|
||||
|
||||
/* transformations */
|
||||
void (* apply_transform) (ClutterActor *actor,
|
||||
CoglMatrix *matrix);
|
||||
|
||||
/* event signals */
|
||||
gboolean (* event) (ClutterActor *actor,
|
||||
ClutterEvent *event);
|
||||
@ -325,7 +334,6 @@ void clutter_actor_get_allocation_geometry (ClutterActor
|
||||
void clutter_actor_get_allocation_vertices (ClutterActor *self,
|
||||
ClutterActor *ancestor,
|
||||
ClutterVertex verts[4]);
|
||||
|
||||
void clutter_actor_set_geometry (ClutterActor *self,
|
||||
const ClutterGeometry *geometry);
|
||||
void clutter_actor_get_geometry (ClutterActor *self,
|
||||
@ -514,6 +522,9 @@ PangoContext *clutter_actor_create_pango_context (ClutterActor *self
|
||||
PangoLayout * clutter_actor_create_pango_layout (ClutterActor *self,
|
||||
const gchar *text);
|
||||
|
||||
void clutter_actor_get_transformation_matrix (ClutterActor *self,
|
||||
CoglMatrix *matrix);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __CLUTTER_ACTOR_H__ */
|
||||
|
@ -363,6 +363,7 @@ clutter_actor_get_transformed_size
|
||||
clutter_actor_get_paint_opacity
|
||||
clutter_actor_get_paint_visibility
|
||||
clutter_actor_get_abs_allocation_vertices
|
||||
clutter_actor_get_transformation_matrix
|
||||
|
||||
<SUBSECTION>
|
||||
clutter_actor_set_anchor_point
|
||||
|
Loading…
Reference in New Issue
Block a user