mirror of
https://github.com/brl/mutter.git
synced 2024-11-26 18:11:05 -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
|
/* Helper macro which translates by the anchor coord, applies the
|
||||||
given transformation and then translates back */
|
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; \
|
gfloat _tx, _ty, _tz; \
|
||||||
clutter_anchor_coord_get_units ((actor), (coord), &_tx, &_ty, &_tz); \
|
clutter_anchor_coord_get_units ((a), (c), &_tx, &_ty, &_tz); \
|
||||||
cogl_translate (_tx, _ty, _tz); \
|
cogl_matrix_translate ((m), _tx, _ty, _tz); \
|
||||||
{ transform; } \
|
{ _transform; } \
|
||||||
cogl_translate (-_tx, -_ty, -_tz); } G_STMT_END
|
cogl_matrix_translate ((m), -_tx, -_ty, -_tz); } G_STMT_END
|
||||||
|
|
||||||
G_DEFINE_ABSTRACT_TYPE_WITH_CODE (ClutterActor,
|
G_DEFINE_ABSTRACT_TYPE_WITH_CODE (ClutterActor,
|
||||||
clutter_actor,
|
clutter_actor,
|
||||||
@ -2119,25 +2119,23 @@ clutter_actor_get_abs_allocation_vertices (ClutterActor *self,
|
|||||||
verts);
|
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
|
static void
|
||||||
_clutter_actor_apply_modelview_transform (ClutterActor *self)
|
clutter_actor_real_apply_transform (ClutterActor *self,
|
||||||
|
CoglMatrix *matrix)
|
||||||
{
|
{
|
||||||
ClutterActorPrivate *priv = self->priv;
|
ClutterActorPrivate *priv = self->priv;
|
||||||
gboolean is_stage = CLUTTER_IS_STAGE (self);
|
gboolean is_stage = CLUTTER_IS_STAGE (self);
|
||||||
|
|
||||||
if (!is_stage)
|
if (!is_stage)
|
||||||
cogl_translate (priv->allocation.x1,
|
{
|
||||||
|
cogl_matrix_translate (matrix,
|
||||||
|
priv->allocation.x1,
|
||||||
priv->allocation.y1,
|
priv->allocation.y1,
|
||||||
0);
|
0.0);
|
||||||
|
}
|
||||||
|
|
||||||
if (priv->z)
|
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
|
* 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)
|
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,
|
&priv->scale_center,
|
||||||
cogl_scale (priv->scale_x,
|
cogl_matrix_scale (matrix,
|
||||||
|
priv->scale_x,
|
||||||
priv->scale_y,
|
priv->scale_y,
|
||||||
1.0));
|
1.0));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (priv->rzang)
|
if (priv->rzang)
|
||||||
TRANSFORM_ABOUT_ANCHOR_COORD (self,
|
TRANSFORM_ABOUT_ANCHOR_COORD (self, matrix,
|
||||||
&priv->rz_center,
|
&priv->rz_center,
|
||||||
cogl_rotate (priv->rzang, 0, 0, 1.0));
|
cogl_matrix_rotate (matrix,
|
||||||
|
priv->rzang,
|
||||||
|
0, 0, 1.0));
|
||||||
|
|
||||||
if (priv->ryang)
|
if (priv->ryang)
|
||||||
TRANSFORM_ABOUT_ANCHOR_COORD (self,
|
TRANSFORM_ABOUT_ANCHOR_COORD (self, matrix,
|
||||||
&priv->ry_center,
|
&priv->ry_center,
|
||||||
cogl_rotate (priv->ryang, 0, 1.0, 0));
|
cogl_matrix_rotate (matrix,
|
||||||
|
priv->ryang,
|
||||||
|
0, 1.0, 0));
|
||||||
|
|
||||||
if (priv->rxang)
|
if (priv->rxang)
|
||||||
TRANSFORM_ABOUT_ANCHOR_COORD (self,
|
TRANSFORM_ABOUT_ANCHOR_COORD (self, matrix,
|
||||||
&priv->rx_center,
|
&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))
|
if (!is_stage && !clutter_anchor_coord_is_zero (&priv->anchor))
|
||||||
{
|
{
|
||||||
gfloat x, y, z;
|
gfloat x, y, z;
|
||||||
|
|
||||||
clutter_anchor_coord_get_units (self, &priv->anchor, &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
|
/* Recursively applies the transforms associated with this actor and
|
||||||
* its ancestors to the OpenGL modelview matrix. Use NULL if you want this
|
* its ancestors to the OpenGL modelview matrix. Use NULL if you want this
|
||||||
* to go all the way down to the stage.
|
* 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->get_preferred_height = clutter_actor_real_get_preferred_height;
|
||||||
klass->allocate = clutter_actor_real_allocate;
|
klass->allocate = clutter_actor_real_allocate;
|
||||||
klass->queue_redraw = clutter_actor_real_queue_redraw;
|
klass->queue_redraw = clutter_actor_real_queue_redraw;
|
||||||
|
klass->apply_transform = clutter_actor_real_apply_transform;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -9163,3 +9191,21 @@ clutter_actor_unset_flags (ClutterActor *self,
|
|||||||
|
|
||||||
g_object_thaw_notify (obj);
|
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
|
* and natural heights of an actor for a given width; it is used by
|
||||||
* clutter_actor_get_preferred_height()
|
* clutter_actor_get_preferred_height()
|
||||||
* @allocate: virtual function, used when settings the coordinates of an
|
* @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
|
* @parent_set: signal class handler for the #ClutterActor::parent-set
|
||||||
* @destroy: signal class handler for #ClutterActor::destroy
|
* @destroy: signal class handler for #ClutterActor::destroy
|
||||||
* @pick: virtual function, used to draw an outline of the actor with
|
* @pick: virtual function, used to draw an outline of the actor with
|
||||||
@ -238,6 +242,11 @@ struct _ClutterActorClass
|
|||||||
void (* allocate) (ClutterActor *actor,
|
void (* allocate) (ClutterActor *actor,
|
||||||
const ClutterActorBox *box,
|
const ClutterActorBox *box,
|
||||||
ClutterAllocationFlags flags);
|
ClutterAllocationFlags flags);
|
||||||
|
|
||||||
|
/* transformations */
|
||||||
|
void (* apply_transform) (ClutterActor *actor,
|
||||||
|
CoglMatrix *matrix);
|
||||||
|
|
||||||
/* event signals */
|
/* event signals */
|
||||||
gboolean (* event) (ClutterActor *actor,
|
gboolean (* event) (ClutterActor *actor,
|
||||||
ClutterEvent *event);
|
ClutterEvent *event);
|
||||||
@ -325,7 +334,6 @@ void clutter_actor_get_allocation_geometry (ClutterActor
|
|||||||
void clutter_actor_get_allocation_vertices (ClutterActor *self,
|
void clutter_actor_get_allocation_vertices (ClutterActor *self,
|
||||||
ClutterActor *ancestor,
|
ClutterActor *ancestor,
|
||||||
ClutterVertex verts[4]);
|
ClutterVertex verts[4]);
|
||||||
|
|
||||||
void clutter_actor_set_geometry (ClutterActor *self,
|
void clutter_actor_set_geometry (ClutterActor *self,
|
||||||
const ClutterGeometry *geometry);
|
const ClutterGeometry *geometry);
|
||||||
void clutter_actor_get_geometry (ClutterActor *self,
|
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,
|
PangoLayout * clutter_actor_create_pango_layout (ClutterActor *self,
|
||||||
const gchar *text);
|
const gchar *text);
|
||||||
|
|
||||||
|
void clutter_actor_get_transformation_matrix (ClutterActor *self,
|
||||||
|
CoglMatrix *matrix);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
#endif /* __CLUTTER_ACTOR_H__ */
|
#endif /* __CLUTTER_ACTOR_H__ */
|
||||||
|
@ -363,6 +363,7 @@ clutter_actor_get_transformed_size
|
|||||||
clutter_actor_get_paint_opacity
|
clutter_actor_get_paint_opacity
|
||||||
clutter_actor_get_paint_visibility
|
clutter_actor_get_paint_visibility
|
||||||
clutter_actor_get_abs_allocation_vertices
|
clutter_actor_get_abs_allocation_vertices
|
||||||
|
clutter_actor_get_transformation_matrix
|
||||||
|
|
||||||
<SUBSECTION>
|
<SUBSECTION>
|
||||||
clutter_actor_set_anchor_point
|
clutter_actor_set_anchor_point
|
||||||
|
Loading…
Reference in New Issue
Block a user