From 8d22fea31c1df87904a82112ef3e917b70d56120 Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Thu, 10 Jun 2010 17:34:48 +0100 Subject: [PATCH 1/5] docs: Fix Effect subclassing section It still mentions the long since removed "prepare" function. --- clutter/clutter-effect.c | 22 +++++----------------- 1 file changed, 5 insertions(+), 17 deletions(-) diff --git a/clutter/clutter-effect.c b/clutter/clutter-effect.c index 0dd781b97..c89f33251 100644 --- a/clutter/clutter-effect.c +++ b/clutter/clutter-effect.c @@ -39,29 +39,17 @@ * * Implementing a ClutterEffect * Creating a sub-class of #ClutterEffect requires the implementation - * of three virtual functions: + * of two virtual functions: * - * prepare(), which is called when - * attaching the #ClutterEffect to a #ClutterActor through the - * clutter_actor_add_effect() function or when the actor is being - * painted; * pre_paint(), which is called * before painting the #ClutterActor. * post_paint(), which is called * after painting the #ClutterActor. * - * The prepare() function receives the - * #ClutterActor to which the effect has been attached to, and it should be - * used to set up the initial state of the effect, for instance depending on - * the actor that has been passed. The function returns a boolean value, - * which is used to determine whether the #ClutterEffect has been prepared or - * not. An unprepared shader will be asked to prepare itself again during the - * actor's paint sequence, and if it fails again it will be ignored. * The pre_paint() function should be used to set * up the #ClutterEffect right before the #ClutterActor's paint - * sequence. This function, like prepare() can fail, and - * return %FALSE; in that case, no post_paint() - * invocation will follow. + * sequence. This function can fail, and return %FALSE; in that case, no + * post_paint() invocation will follow. * The post_paint() function is called after the * #ClutterActor's paint sequence. * The pre_paint() phase could be seen as a custom @@ -73,8 +61,8 @@ * A simple ClutterEffect implementation * The example below creates two rectangles: one will be painted * "behind" the actor, while another will be painted "on top" of the actor. - * The prepare() phase will create the two materials - * used for the two different rectangles; the + * The set_actor() implementation will create the two + * materials used for the two different rectangles; the * pre_paint() function will paint the first material * using cogl_rectangle(), while the post_paint() * phase will paint the second material. From fa381cc36194fbefd26717b1b3031018d5a1400e Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Thu, 10 Jun 2010 17:35:56 +0100 Subject: [PATCH 2/5] offscreen-effect: Traslate the modelview with the offsets Instead of using the stage offsets when painting we can simply traslate the current modelview. This allows sub-classes to fully override the paint_target() virtual function without chaining up. --- clutter/clutter-offscreen-effect.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/clutter/clutter-offscreen-effect.c b/clutter/clutter-offscreen-effect.c index e3ce81752..009d44d80 100644 --- a/clutter/clutter-offscreen-effect.c +++ b/clutter/clutter-offscreen-effect.c @@ -316,12 +316,12 @@ clutter_offscreen_effect_real_paint_target (ClutterOffscreenEffect *effect) /* paint the texture at the same position as the actor would be, * in Stage coordinates, since we set up the modelview matrix to - * be exactly as the stage sets it up + * be exactly as the stage sets it up, plus the eventual offsets + * due to offscreen effects stacking */ - cogl_rectangle_with_texture_coords (priv->x_offset, - priv->y_offset, - priv->x_offset + priv->target_width, - priv->y_offset + priv->target_height, + cogl_rectangle_with_texture_coords (0, 0, + priv->target_width, + priv->target_height, 0.0, 0.0, 1.0, 1.0); } @@ -364,6 +364,8 @@ clutter_offscreen_effect_post_paint (ClutterEffect *effect) cogl_push_matrix (); + cogl_translate (priv->x_offset, priv->y_offset, 0.0f); + /* paint the target material; this is virtualized for * sub-classes that require special hand-holding */ From c2081a076c3fdd376d2cd97c11f811e4a6549926 Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Wed, 9 Jun 2010 17:52:06 +0100 Subject: [PATCH 3/5] effect: Add DeformEffect DeformEffect is an abstract class that should be used to write effects that change the geometry of an actor before submitting it to the GPU. Just like the ShaderEffect class, DeformEffect renders the actor to which it has been applied into an FBO; then it creates a mesh and stores it inside a VBO. Sub-classes can control vertex attributes like position, texel coordinates and the color. --- clutter/Makefile.am | 2 + clutter/clutter-deform-effect.c | 739 ++++++++++++++++++++++++++++++++ clutter/clutter-deform-effect.h | 111 +++++ clutter/clutter.h | 1 + 4 files changed, 853 insertions(+) create mode 100644 clutter/clutter-deform-effect.c create mode 100644 clutter/clutter-deform-effect.h diff --git a/clutter/Makefile.am b/clutter/Makefile.am index c514406ff..e658c58f6 100644 --- a/clutter/Makefile.am +++ b/clutter/Makefile.am @@ -95,6 +95,7 @@ source_h = \ $(srcdir)/clutter-colorize-effect.h \ $(srcdir)/clutter-constraint.h \ $(srcdir)/clutter-container.h \ + $(srcdir)/clutter-deform-effect.h \ $(srcdir)/clutter-deprecated.h \ $(srcdir)/clutter-desaturate-effect.h \ $(srcdir)/clutter-device-manager.h \ @@ -182,6 +183,7 @@ source_c = \ $(srcdir)/clutter-colorize-effect.c \ $(srcdir)/clutter-constraint.c \ $(srcdir)/clutter-container.c \ + $(srcdir)/clutter-deform-effect.c \ $(srcdir)/clutter-desaturate-effect.c \ $(srcdir)/clutter-device-manager.c \ $(srcdir)/clutter-drag-action.c \ diff --git a/clutter/clutter-deform-effect.c b/clutter/clutter-deform-effect.c new file mode 100644 index 000000000..ff96816f1 --- /dev/null +++ b/clutter/clutter-deform-effect.c @@ -0,0 +1,739 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2010 Intel Corporation. + * + * 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 . + * + * Author: + * Emmanuele Bassi + * + * Based on the MxDeformTexture class, written by: + * Chris Lord + */ + +/** + * SECTION:clutter-deform-effect + * @Title: ClutterDeformEffect + * @Short_Description: A base class for effects deforming the geometry + * of an actor + * + * #ClutterDeformEffect is an abstract class providing all the plumbing + * for creating effects that result in the deformation of an actor's + * geometry. + * + * #ClutterDeformEffect uses offscreen buffers to render the contents of + * a #ClutterActor and then the Cogl vertex buffers API to submit the + * geomtry to the GPU. + * + * + * Implementing ClutterDeformEffect + * Sub-classes of #ClutterDeformEffect should override the + * deform_vertex() virtual function; this function + * is called on every vertex that needs to be deformed by the effect. + * Each passed vertex is an in-out parameter that initially contains the + * position of the vertex and should be modified according to a specific + * deformation algorithm. + * + * + * #ClutterDeformEffect is available since Clutter 1.4 + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "clutter-deform-effect.h" + +#include + +#include "clutter-debug.h" +#include "clutter-enum-types.h" +#include "clutter-private.h" + +#define DEFAULT_N_TILES 32 + +struct _ClutterDeformEffectPrivate +{ + CoglHandle back_material; + + gint x_tiles; + gint y_tiles; + + CoglHandle vbo; + + CoglHandle indices; + CoglHandle back_indices; + gint n_indices; + + CoglTextureVertex *vertices; + + gulong allocation_id; + + guint is_dirty : 1; +}; + +enum +{ + PROP_0, + + PROP_X_TILES, + PROP_Y_TILES, + + PROP_BACK_MATERIAL +}; + +G_DEFINE_ABSTRACT_TYPE (ClutterDeformEffect, + clutter_deform_effect, + CLUTTER_TYPE_OFFSCREEN_EFFECT); + +static void +clutter_deform_effect_real_deform_vertex (ClutterDeformEffect *effect, + gfloat width, + gfloat height, + CoglTextureVertex *vertex) +{ + g_warning ("%s: Deformation effect of type '%s' does not implement " + "the required ClutterDeformEffect::deform_vertex virtual " + "function.", + G_STRLOC, + G_OBJECT_TYPE_NAME (effect)); +} + +void +_clutter_deform_effect_deform_vertex (ClutterDeformEffect *effect, + gfloat width, + gfloat height, + CoglTextureVertex *vertex) +{ + CLUTTER_DEFORM_EFFECT_GET_CLASS (effect)->deform_vertex (effect, + width, height, + vertex); +} + +static void +vbo_invalidate (ClutterActor *actor, + const ClutterActorBox *allocation, + ClutterAllocationFlags flags, + ClutterDeformEffect *effect) +{ + effect->priv->is_dirty = TRUE; +} + +static void +clutter_deform_effect_set_actor (ClutterActorMeta *meta, + ClutterActor *actor) +{ + ClutterDeformEffectPrivate *priv = CLUTTER_DEFORM_EFFECT (meta)->priv; + + if (priv->allocation_id != 0) + { + ClutterActor *old_actor = clutter_actor_meta_get_actor (meta); + + g_signal_handler_disconnect (old_actor, priv->allocation_id); + priv->allocation_id = 0; + } + + /* we need to invalidate the VBO whenever the allocation of the actor + * changes + */ + if (actor != NULL) + priv->allocation_id = g_signal_connect (actor, "allocation-changed", + G_CALLBACK (vbo_invalidate), + meta); + + priv->is_dirty = TRUE; + + CLUTTER_ACTOR_META_CLASS (clutter_deform_effect_parent_class)->set_actor (meta, actor); +} + +static void +clutter_deform_effect_paint_target (ClutterOffscreenEffect *effect) +{ + ClutterDeformEffect *self= CLUTTER_DEFORM_EFFECT (effect); + ClutterDeformEffectPrivate *priv = self->priv; + gboolean is_depth_enabled, is_cull_enabled; + CoglHandle material; + gint n_tiles; + + if (priv->is_dirty) + { + ClutterActor *actor; + gfloat width, height; + guint opacity; + gint i, j; + + actor = clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (effect)); + opacity = clutter_actor_get_paint_opacity (actor); + clutter_actor_get_size (actor, &width, &height); + + for (i = 0; i < priv->y_tiles + 1; i++) + { + for (j = 0; j < priv->x_tiles + 1; j++) + { + CoglTextureVertex *vertex; + + vertex = &priv->vertices[(i * (priv->x_tiles + 1)) + j]; + + vertex->tx = (float) j / priv->x_tiles; + vertex->ty = (float) i / priv->y_tiles; + + vertex->x = width * vertex->tx; + vertex->y = height * vertex->ty; + vertex->z = 0.0f; + + cogl_color_set_from_4ub (&vertex->color, 255, 255, 255, opacity); + + _clutter_deform_effect_deform_vertex (self, width, height, vertex); + } + } + + /* XXX in theory, the sub-classes should tell us what they changed + * in the texture vertices; we then would be able to avoid resubmitting + * the same data, if it did not change. for the time being, we resubmit + * everything + */ + cogl_vertex_buffer_add (priv->vbo, "gl_Vertex", + 3, + COGL_ATTRIBUTE_TYPE_FLOAT, + FALSE, + sizeof (CoglTextureVertex), + &priv->vertices->x); + cogl_vertex_buffer_add (priv->vbo, "gl_MultiTexCoord0", + 2, + COGL_ATTRIBUTE_TYPE_FLOAT, + FALSE, + sizeof (CoglTextureVertex), + &priv->vertices->tx); + cogl_vertex_buffer_add (priv->vbo, "gl_Color", + 4, + COGL_ATTRIBUTE_TYPE_UNSIGNED_BYTE, + FALSE, + sizeof (CoglTextureVertex), + &priv->vertices->color); + + priv->is_dirty = FALSE; + } + + /* enable depth test, if it's not already enabled */ + is_depth_enabled = cogl_get_depth_test_enabled (); + if (!is_depth_enabled) + cogl_set_depth_test_enabled (TRUE); + + /* enable backface culling if it's not already enabled and if + * we have a back material + */ + is_cull_enabled = cogl_get_backface_culling_enabled (); + if (priv->back_material != COGL_INVALID_HANDLE && !is_cull_enabled) + cogl_set_backface_culling_enabled (TRUE); + else if (priv->back_material == COGL_INVALID_HANDLE && is_cull_enabled) + cogl_set_backface_culling_enabled (FALSE); + + n_tiles = (priv->x_tiles + 1) * (priv->y_tiles + 1); + + /* draw the front */ + material = clutter_offscreen_effect_get_target (effect); + if (material != COGL_INVALID_HANDLE) + { + cogl_set_source (material); + cogl_vertex_buffer_draw_elements (priv->vbo, + COGL_VERTICES_MODE_TRIANGLE_STRIP, + priv->indices, + 0, + n_tiles, + 0, + priv->n_indices); + } + + /* draw the back */ + material = priv->back_material; + if (material != COGL_INVALID_HANDLE) + { + cogl_set_source (priv->back_material); + cogl_vertex_buffer_draw_elements (priv->vbo, + COGL_VERTICES_MODE_TRIANGLE_STRIP, + priv->back_indices, + 0, + n_tiles, + 0, + priv->n_indices); + } + + /* restore the previous state */ + if (!is_depth_enabled) + cogl_set_depth_test_enabled (FALSE); + + if (priv->back_material != COGL_INVALID_HANDLE && !is_cull_enabled) + cogl_set_backface_culling_enabled (FALSE); + else if (priv->back_material == COGL_INVALID_HANDLE && is_cull_enabled) + cogl_set_backface_culling_enabled (TRUE); +} + +static inline void +clutter_deform_effect_free_arrays (ClutterDeformEffect *self) +{ + ClutterDeformEffectPrivate *priv = self->priv; + + if (priv->vbo != COGL_INVALID_HANDLE) + { + cogl_handle_unref (priv->vbo); + priv->vbo = COGL_INVALID_HANDLE; + } + + if (priv->indices != COGL_INVALID_HANDLE) + { + cogl_handle_unref (priv->indices); + priv->indices = COGL_INVALID_HANDLE; + } + + g_free (priv->vertices); + priv->vertices = NULL; +} + +static void +clutter_deform_effect_init_arrays (ClutterDeformEffect *self) +{ + ClutterDeformEffectPrivate *priv = self->priv; + GLushort *static_indices, *static_back_indices; + GLushort *idx, *back_idx; + gint x, y, direction; + gint n_tiles; + + clutter_deform_effect_free_arrays (self); + + priv->n_indices = (2 + 2 * priv->x_tiles) + * priv->y_tiles + + (priv->y_tiles - 1); + + static_indices = g_new (GLushort, priv->n_indices); + static_back_indices = g_new (GLushort, priv->n_indices); + +#define MESH_INDEX(x,y) ((y) * (priv->x_tiles + 1) + (x)) + + /* compute all the triangles from the various tiles */ + direction = 1; + + idx = static_indices; + idx[0] = MESH_INDEX (0, 0); + idx[1] = MESH_INDEX (0, 1); + idx += 2; + + back_idx = static_back_indices; + back_idx[0] = MESH_INDEX (priv->x_tiles, 0); + back_idx[1] = MESH_INDEX (priv->x_tiles, 1); + back_idx += 2; + + for (y = 0; y < priv->y_tiles; y++) + { + for (x = 0; x < priv->x_tiles; x++) + { + if (direction) + { + idx[0] = MESH_INDEX (x + 1, y); + idx[1] = MESH_INDEX (x + 1, y + 1); + + back_idx[0] = MESH_INDEX (priv->x_tiles - (x + 1), y); + back_idx[1] = MESH_INDEX (priv->x_tiles - (x + 1), y + 1); + } + else + { + idx[0] = MESH_INDEX (priv->x_tiles - x - 1, y); + idx[1] = MESH_INDEX (priv->x_tiles - x - 1, y + 1); + + back_idx[0] = MESH_INDEX (x + 1, y); + back_idx[1] = MESH_INDEX (x + 1, y + 1); + } + + idx += 2; + back_idx += 2; + } + + if (y == (priv->y_tiles - 1)) + break; + + if (direction) + { + idx[0] = MESH_INDEX (priv->x_tiles, y + 1); + idx[1] = MESH_INDEX (priv->x_tiles, y + 1); + idx[2] = MESH_INDEX (priv->x_tiles, y + 2); + + back_idx[0] = MESH_INDEX (0, y + 1); + back_idx[1] = MESH_INDEX (0, y + 1); + back_idx[2] = MESH_INDEX (0, y + 2); + } + else + { + idx[0] = MESH_INDEX (0, y + 1); + idx[1] = MESH_INDEX (0, y + 1); + idx[2] = MESH_INDEX (0, y + 2); + + back_idx[0] = MESH_INDEX (priv->x_tiles, y + 1); + back_idx[1] = MESH_INDEX (priv->x_tiles, y + 1); + back_idx[2] = MESH_INDEX (priv->x_tiles, y + 2); + } + + idx += 3; + back_idx += 3; + + direction = !direction; + } + +#undef MESH_INDEX + + priv->indices = + cogl_vertex_buffer_indices_new (COGL_INDICES_TYPE_UNSIGNED_SHORT, + static_indices, + priv->n_indices); + priv->back_indices = + cogl_vertex_buffer_indices_new (COGL_INDICES_TYPE_UNSIGNED_SHORT, + static_back_indices, + priv->n_indices); + + g_free (static_indices); + g_free (static_back_indices); + + n_tiles = (priv->x_tiles + 1) * (priv->y_tiles + 1); + priv->vertices = g_new (CoglTextureVertex, n_tiles); + priv->vbo = cogl_vertex_buffer_new (n_tiles); + + priv->is_dirty = TRUE; +} + +static inline void +clutter_deform_effect_free_back_material (ClutterDeformEffect *self) +{ + ClutterDeformEffectPrivate *priv = self->priv; + + if (priv->back_material != NULL) + { + cogl_handle_unref (priv->back_material); + priv->back_material = COGL_INVALID_HANDLE; + } +} + +static void +clutter_deform_effect_finalize (GObject *gobject) +{ + ClutterDeformEffect *self = CLUTTER_DEFORM_EFFECT (gobject); + + clutter_deform_effect_free_arrays (self); + clutter_deform_effect_free_back_material (self); + + G_OBJECT_CLASS (clutter_deform_effect_parent_class)->finalize (gobject); +} + +static void +clutter_deform_effect_set_property (GObject *gobject, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + ClutterDeformEffect *self = CLUTTER_DEFORM_EFFECT (gobject); + + switch (prop_id) + { + case PROP_X_TILES: + clutter_deform_effect_set_n_tiles (self, g_value_get_uint (value), + self->priv->y_tiles); + break; + + case PROP_Y_TILES: + clutter_deform_effect_set_n_tiles (self, self->priv->x_tiles, + g_value_get_uint (value)); + break; + + case PROP_BACK_MATERIAL: + clutter_deform_effect_set_back_material (self, g_value_get_boxed (value)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + break; + } +} + +static void +clutter_deform_effect_get_property (GObject *gobject, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + ClutterDeformEffectPrivate *priv = CLUTTER_DEFORM_EFFECT (gobject)->priv; + + switch (prop_id) + { + case PROP_X_TILES: + g_value_set_uint (value, priv->x_tiles); + break; + + case PROP_Y_TILES: + g_value_set_uint (value, priv->y_tiles); + break; + + case PROP_BACK_MATERIAL: + g_value_set_boxed (value, priv->back_material); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + break; + } +} + +static void +clutter_deform_effect_class_init (ClutterDeformEffectClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + ClutterActorMetaClass *meta_class = CLUTTER_ACTOR_META_CLASS (klass); + ClutterOffscreenEffectClass *offscreen_class = CLUTTER_OFFSCREEN_EFFECT_CLASS (klass); + GParamSpec *pspec; + + g_type_class_add_private (klass, sizeof (ClutterDeformEffectPrivate)); + + klass->deform_vertex = clutter_deform_effect_real_deform_vertex; + + gobject_class->set_property = clutter_deform_effect_set_property; + gobject_class->get_property = clutter_deform_effect_get_property; + gobject_class->finalize = clutter_deform_effect_finalize; + + /** + * ClutterDeformEffect:x-tiles: + * + * The number of horizontal tiles. The bigger the number, the + * smaller the tiles + * + * Since: 1.4 + */ + pspec = g_param_spec_uint ("x-tiles", + "Horiontal Tiles", + "The number of horizontal tiles", + 1, G_MAXUINT, + DEFAULT_N_TILES, + CLUTTER_PARAM_READWRITE); + g_object_class_install_property (gobject_class, PROP_X_TILES, pspec); + + /** + * ClutterDeformEffect:y-tiles: + * + * The number of vertical tiles. The bigger the number, the + * smaller the tiles + * + * Since: 1.4 + */ + pspec = g_param_spec_uint ("y-tiles", + "Vertical Tiles", + "The number of vertical tiles", + 1, G_MAXUINT, + DEFAULT_N_TILES, + CLUTTER_PARAM_READWRITE); + g_object_class_install_property (gobject_class, PROP_Y_TILES, pspec); + + /** + * ClutterDeformEffect:back-material: + * + * A material to be used when painting the back of the actor + * to which this effect has been applied + * + * By default, no material will be used + * + * Since: 1.4 + */ + pspec = g_param_spec_boxed ("back-material", + "Back Material", + "The material to be used when painting the " + "back of the actor", + COGL_TYPE_HANDLE, + CLUTTER_PARAM_READWRITE); + g_object_class_install_property (gobject_class, PROP_BACK_MATERIAL, pspec); + + meta_class->set_actor = clutter_deform_effect_set_actor; + + offscreen_class->paint_target = clutter_deform_effect_paint_target; +} + +static void +clutter_deform_effect_init (ClutterDeformEffect *self) +{ + self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, CLUTTER_TYPE_DEFORM_EFFECT, + ClutterDeformEffectPrivate); + + self->priv->x_tiles = self->priv->y_tiles = DEFAULT_N_TILES; + self->priv->back_material = COGL_INVALID_HANDLE; + + clutter_deform_effect_init_arrays (self); +} + +/** + * clutter_deform_effect_set_back_material: + * @effect: a #ClutterDeformEffect + * @material: (allow-none): a handle to a Cogl material + * + * Sets the material that should be used when drawing the back face + * of the actor during a deformation + * + * The #ClutterDeformEffect will take a reference on the material's + * handle + * + * Since: 1.4 + */ +void +clutter_deform_effect_set_back_material (ClutterDeformEffect *effect, + CoglHandle material) +{ + ClutterDeformEffectPrivate *priv; + + g_return_if_fail (CLUTTER_IS_DEFORM_EFFECT (effect)); + g_return_if_fail (material == COGL_INVALID_HANDLE || cogl_is_material (material)); + + priv = effect->priv; + + clutter_deform_effect_free_back_material (effect); + + priv->back_material = material; + if (priv->back_material != COGL_INVALID_HANDLE) + cogl_handle_ref (priv->back_material); + + clutter_deform_effect_invalidate (effect); +} + +/** + * clutter_deform_effect_get_back_material: + * @effect: a #ClutterDeformEffect + * + * Retrieves the handle to the back face material used by @effect + * + * Return value: (transfer none): a handle for the material, or %NULL. + * The returned material is owned by the #ClutterDeformEffect and it + * should not be freed directly + * + * Since: 1.4 + */ +CoglHandle +clutter_deform_effect_get_back_material (ClutterDeformEffect *effect) +{ + g_return_val_if_fail (CLUTTER_IS_DEFORM_EFFECT (effect), NULL); + + return effect->priv->back_material; +} + +/** + * clutter_deform_effect_set_n_tiles: + * @effect: a #ClutterDeformEffect + * @x_tiles: number of horizontal tiles + * @y_tiles: number of vertical tiles + * + * Sets the number of horizontal and vertical tiles to be used + * when applying the effect + * + * More tiles allow a finer grained deformation at the expenses + * of computation + * + * Since: 1.4 + */ +void +clutter_deform_effect_set_n_tiles (ClutterDeformEffect *effect, + guint x_tiles, + guint y_tiles) +{ + ClutterDeformEffectPrivate *priv; + gboolean tiles_changed = FALSE; + + g_return_if_fail (CLUTTER_IS_DEFORM_EFFECT (effect)); + g_return_if_fail (x_tiles > 0 && y_tiles > 0); + + priv = effect->priv; + + g_object_freeze_notify (G_OBJECT (effect)); + + if (priv->x_tiles != x_tiles) + { + priv->x_tiles = x_tiles; + + g_object_notify (G_OBJECT (effect), "x-tiles"); + + tiles_changed = TRUE; + } + + if (priv->y_tiles != y_tiles) + { + priv->y_tiles = y_tiles; + + g_object_notify (G_OBJECT (effect), "y-tiles"); + + tiles_changed = TRUE; + } + + if (tiles_changed) + { + clutter_deform_effect_init_arrays (effect); + clutter_deform_effect_invalidate (effect); + } + + g_object_thaw_notify (G_OBJECT (effect)); +} + +/** + * clutter_deform_effect_get_n_tiles: + * @effect: a #ClutterDeformEffect + * @x_tiles: (out): return location for the number of horizontal tiles, + * or %NULL + * @y_tiles: (out): return location for the number of vertical tiles, + * or %NULL + * + * Retrieves the number of horizontal and vertical tiles used to sub-divide + * the actor's geometry during the effect + * + * Since: 1.4 + */ +void +clutter_deform_effect_get_n_tiles (ClutterDeformEffect *effect, + guint *x_tiles, + guint *y_tiles) +{ + g_return_if_fail (CLUTTER_IS_DEFORM_EFFECT (effect)); + + if (x_tiles != NULL) + *x_tiles = effect->priv->x_tiles; + + if (y_tiles != NULL) + *y_tiles = effect->priv->y_tiles; +} + +/** + * clutter_deform_effect_invalidate: + * @effect: a #ClutterDeformEffect + * + * Invalidates the @effect's vertices and, if it is associated + * to an actor, it will queue a redraw + * + * Since: 1.4 + */ +void +clutter_deform_effect_invalidate (ClutterDeformEffect *effect) +{ + ClutterActor *actor; + + g_return_if_fail (CLUTTER_IS_DEFORM_EFFECT (effect)); + + if (effect->priv->is_dirty) + return; + + effect->priv->is_dirty = TRUE; + + actor = clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (effect)); + if (actor != NULL) + clutter_actor_queue_redraw (actor); +} diff --git a/clutter/clutter-deform-effect.h b/clutter/clutter-deform-effect.h new file mode 100644 index 000000000..63ccd4c5a --- /dev/null +++ b/clutter/clutter-deform-effect.h @@ -0,0 +1,111 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2010 Intel Corporation. + * + * 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 . + * + * Author: + * Emmanuele Bassi + */ + +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __CLUTTER_DEFORM_EFFECT_H__ +#define __CLUTTER_DEFORM_EFFECT_H__ + +#include +#include + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_DEFORM_EFFECT (clutter_deform_effect_get_type ()) +#define CLUTTER_DEFORM_EFFECT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_DEFORM_EFFECT, ClutterDeformEffect)) +#define CLUTTER_IS_DEFORM_EFFECT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_DEFORM_EFFECT)) +#define CLUTTER_DEFORM_EFFECT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_DEFORM_EFFECT, ClutterDeformEffectClass)) +#define CLUTTER_IS_DEFORM_EFFECT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_DEFORM_EFFECT)) +#define CLUTTER_DEFORM_EFFECT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_DEFORM_EFFECT, ClutterDeformEffectClass)) + +typedef struct _ClutterDeformEffect ClutterDeformEffect; +typedef struct _ClutterDeformEffectPrivate ClutterDeformEffectPrivate; +typedef struct _ClutterDeformEffectClass ClutterDeformEffectClass; + +/** + * ClutterDeformEffect: + * + * The ClutterDeformEffect structure contains + * only private data and should be accessed using the provided API + * + * Since: 1.4 + */ +struct _ClutterDeformEffect +{ + /*< private >*/ + ClutterOffscreenEffect parent_instance; + + ClutterDeformEffectPrivate *priv; +}; + +/** + * ClutterDeformEffectClass: + * @deform_vertex: virtual function; sub-classes should override this + * function to compute the deformation of each vertex + * + * The ClutterDeformEffectClass structure contains + * only private data + * + * Since: 1.4 + */ +struct _ClutterDeformEffectClass +{ + /*< private >*/ + ClutterOffscreenEffectClass parent_class; + + /*< public >*/ + void (* deform_vertex) (ClutterDeformEffect *effect, + gfloat width, + gfloat height, + CoglTextureVertex *vertex); + + /*< private >*/ + void (*_clutter_deform1) (void); + void (*_clutter_deform2) (void); + void (*_clutter_deform3) (void); + void (*_clutter_deform4) (void); + void (*_clutter_deform5) (void); + void (*_clutter_deform6) (void); + void (*_clutter_deform7) (void); +}; + +GType clutter_deform_effect_get_type (void) G_GNUC_CONST; + +void clutter_deform_effect_set_back_material (ClutterDeformEffect *effect, + CoglHandle material); +CoglHandle clutter_deform_effect_get_back_material (ClutterDeformEffect *effect); +void clutter_deform_effect_set_n_tiles (ClutterDeformEffect *effect, + guint x_tiles, + guint y_tiles); +void clutter_deform_effect_get_n_tiles (ClutterDeformEffect *effect, + guint *x_tiles, + guint *y_tiles); + +void clutter_deform_effect_invalidate (ClutterDeformEffect *effect); + +G_END_DECLS + +#endif /* __CLUTTER_DEFORM_EFFECT_H__ */ diff --git a/clutter/clutter.h b/clutter/clutter.h index 0b948af95..70c8fa37b 100644 --- a/clutter/clutter.h +++ b/clutter/clutter.h @@ -60,6 +60,7 @@ #include "clutter-colorize-effect.h" #include "clutter-constraint.h" #include "clutter-container.h" +#include "clutter-deform-effect.h" #include "clutter-desaturate-effect.h" #include "clutter-device-manager.h" #include "clutter-drag-action.h" From 44f300b3a242eb722cc1c82129e5e86daa3eb65d Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Thu, 10 Jun 2010 16:56:16 +0100 Subject: [PATCH 4/5] effect: Add PageTurnEffect A simple deformation effect that simulates a page curl. Ported from MxDeformPageTurn inside the Mx toolkit, written by Chris Lord. --- clutter/Makefile.am | 2 + clutter/clutter-page-turn-effect.c | 417 +++++++++++++++++++++++++++++ clutter/clutter-page-turn-effect.h | 71 +++++ clutter/clutter.h | 1 + tests/interactive/test-drag.c | 25 ++ 5 files changed, 516 insertions(+) create mode 100644 clutter/clutter-page-turn-effect.c create mode 100644 clutter/clutter-page-turn-effect.h diff --git a/clutter/Makefile.am b/clutter/Makefile.am index e658c58f6..f38273929 100644 --- a/clutter/Makefile.am +++ b/clutter/Makefile.am @@ -118,6 +118,7 @@ source_h = \ $(srcdir)/clutter-media.h \ $(srcdir)/clutter-model.h \ $(srcdir)/clutter-offscreen-effect.h \ + $(srcdir)/clutter-page-turn-effect.h \ $(srcdir)/clutter-path.h \ $(srcdir)/clutter-rectangle.h \ $(srcdir)/clutter-score.h \ @@ -207,6 +208,7 @@ source_c = \ $(srcdir)/clutter-media.c \ $(srcdir)/clutter-model.c \ $(srcdir)/clutter-offscreen-effect.c \ + $(srcdir)/clutter-page-turn-effect.c \ $(srcdir)/clutter-path.c \ $(srcdir)/clutter-rectangle.c \ $(srcdir)/clutter-score.c \ diff --git a/clutter/clutter-page-turn-effect.c b/clutter/clutter-page-turn-effect.c new file mode 100644 index 000000000..4c8227a7f --- /dev/null +++ b/clutter/clutter-page-turn-effect.c @@ -0,0 +1,417 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2010 Intel Corporation. + * + * 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 . + * + * Author: + * Emmanuele Bassi + * + * Based on MxDeformPageTurn, written by: + * Chris Lord + */ + +/** + * SECTION:clutter-page-turn-effect + * @Title: ClutterPageTurnEffect + * @Short_Description: A page turning effect + * + * A simple page turning effect + * + * #ClutterPageTurnEffect is available since Clutter 1.4 + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "clutter-page-turn-effect.h" + +#include "clutter-debug.h" +#include "clutter-private.h" + +#define CLUTTER_PAGE_TURN_EFFECT_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), CLUTTER_TYPE_PAGE_TURN_EFFECT, ClutterPageTurnEffectClass)) +#define CLUTTER_IS_PAGE_TURN_EFFECT_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), CLUTTER_TYPE_PAGE_TURN_EFFECT)) +#define CLUTTER_PAGE_TURN_EFFECT_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), CLUTTER_TYPE_PAGE_TURN_EFFECT, ClutterPageTurnEffectClass)) + +typedef struct _ClutterPageTurnEffectClass ClutterPageTurnEffectClass; + +struct _ClutterPageTurnEffect +{ + ClutterDeformEffect parent_instance; + + gdouble period; + gdouble angle; + + gfloat radius; +}; + +struct _ClutterPageTurnEffectClass +{ + ClutterDeformEffectClass parent_class; +}; + +enum +{ + PROP_0, + + PROP_PERIOD, + PROP_ANGLE, + PROP_RADIUS +}; + +G_DEFINE_TYPE (ClutterPageTurnEffect, + clutter_page_turn_effect, + CLUTTER_TYPE_DEFORM_EFFECT); + +static void +clutter_page_turn_effect_deform_vertex (ClutterDeformEffect *effect, + gfloat width, + gfloat height, + CoglTextureVertex *vertex) +{ + ClutterPageTurnEffect *self = CLUTTER_PAGE_TURN_EFFECT (effect); + gfloat cx, cy, rx, ry, radians, turn_angle; + guint shade; + + if (self->period == 0.0) + return; + + radians = self->angle * 180.0f / G_PI; + + /* Rotate the point around the centre of the page-curl ray to align it with + * the y-axis. + */ + cx = (1.f - self->period) * width; + cy = (1.f - self->period) * height; + + rx = ((vertex->x - cx) * cos (- radians)) + - ((vertex->y - cy) * sin (- radians)) + - self->radius; + ry = ((vertex->x - cx) * sin (- radians)) + + ((vertex->y - cy) * cos (- radians)); + + turn_angle = 0.f; + if (rx > self->radius * -2.0f) + { + /* Calculate the curl angle as a function from the distance of the curl + * ray (i.e. the page crease) + */ + turn_angle = (rx / self->radius * G_PI_2) - G_PI_2; + shade = (sin (turn_angle) * 96.0f) + 159.0f; + + /* Add a gradient that makes it look like lighting and hides the switch + * between textures. + */ + cogl_color_set_from_4ub (&vertex->color, shade, shade, shade, 0xff); + } + + if (rx > 0) + { + /* Make the curl radius smaller as more circles are formed (stops + * z-fighting and looks cool). Note that 10 is a semi-arbitrary + * number here - divide it by two and it's the amount of space + * between curled layers of the texture, in pixels. + */ + gfloat small_radius; + + small_radius = self->radius + - MIN (self->radius, (turn_angle * 10) / G_PI); + + /* Calculate a point on a cylinder (maybe make this a cone at some + * point) and rotate it by the specified angle. + */ + rx = (small_radius * cos (turn_angle)) + self->radius; + + vertex->x = (rx * cos (radians)) - (ry * sin (radians)) + cx; + vertex->y = (rx * sin (radians)) + (ry * cos (radians)) + cy; + vertex->z = (small_radius * sin (turn_angle)) + self->radius; + } +} + +static void +clutter_page_turn_effect_set_property (GObject *gobject, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + ClutterPageTurnEffect *effect = CLUTTER_PAGE_TURN_EFFECT (gobject); + + switch (prop_id) + { + case PROP_PERIOD: + clutter_page_turn_effect_set_period (effect, g_value_get_double (value)); + break; + + case PROP_ANGLE: + clutter_page_turn_effect_set_angle (effect, g_value_get_double (value)); + break; + + case PROP_RADIUS: + clutter_page_turn_effect_set_radius (effect, g_value_get_float (value)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + break; + } +} + +static void +clutter_page_turn_effect_get_property (GObject *gobject, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + ClutterPageTurnEffect *effect = CLUTTER_PAGE_TURN_EFFECT (gobject); + + switch (prop_id) + { + case PROP_PERIOD: + g_value_set_double (value, effect->period); + break; + + case PROP_ANGLE: + g_value_set_double (value, effect->angle); + break; + + case PROP_RADIUS: + g_value_set_float (value, effect->radius); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + break; + } +} + +static void +clutter_page_turn_effect_class_init (ClutterPageTurnEffectClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + ClutterDeformEffectClass *deform_class = CLUTTER_DEFORM_EFFECT_CLASS (klass); + GParamSpec *pspec; + + gobject_class->set_property = clutter_page_turn_effect_set_property; + gobject_class->get_property = clutter_page_turn_effect_get_property; + + /** + * ClutterPageTurnEffect:period: + * + * The period of the page turn, between 0.0 (no curling) and + * 1.0 (fully curled) + * + * Since: 1.4 + */ + pspec = g_param_spec_double ("period", + "Period", + "The period of the page turn", + 0.0, 1.0, + 0.0, + CLUTTER_PARAM_READWRITE); + g_object_class_install_property (gobject_class, PROP_PERIOD, pspec); + + /** + * ClutterPageTurnEffect:angle: + * + * The angle of the page rotation, in degrees, between 0.0 and 360.0 + * + * Since: 1.4 + */ + pspec = g_param_spec_double ("angle", + "Angle", + "The angle of the page rotation, in degrees", + 0.0, 360.0, + 0.0, + CLUTTER_PARAM_READWRITE); + g_object_class_install_property (gobject_class, PROP_ANGLE, pspec); + + /** + * ClutterPageTurnEffect:radius: + * + * The radius of the page curl, in pixels + * + * Since: 1.4 + */ + pspec = g_param_spec_float ("radius", + "Radius", + "The radius of the page curl", + -G_MAXFLOAT, G_MAXFLOAT, + 24.0, + CLUTTER_PARAM_READWRITE); + g_object_class_install_property (gobject_class, PROP_RADIUS, pspec); + + deform_class->deform_vertex = clutter_page_turn_effect_deform_vertex; +} + +static void +clutter_page_turn_effect_init (ClutterPageTurnEffect *self) +{ + self->period = 0.0; + self->angle = 0.0; + self->radius = 24.0f; +} + +/** + * clutter_page_turn_effect_new: + * @period: the period of the page curl, between 0.0 and 1.0 + * @angle: the angle of the page curl, between 0.0 and 360.0 + * @radius: the radius of the page curl, in pixels + * + * Creates a new #ClutterPageTurnEffect instance with the given parameters + * + * Return value: the newly created #ClutterPageTurnEffect + * + * Since: 1.4 + */ +ClutterEffect * +clutter_page_turn_effect_new (gdouble period, + gdouble angle, + gfloat radius) +{ + g_return_val_if_fail (period >= 0.0 && period <= 1.0, NULL); + g_return_val_if_fail (angle >= 0.0 && angle <= 360.0, NULL); + + return g_object_new (CLUTTER_TYPE_PAGE_TURN_EFFECT, + "period", period, + "angle", angle, + "radius", radius, + NULL); +} + +/** + * clutter_page_turn_effect_set_period: + * @effect: a #ClutterPageTurnEffect + * @period: the period of the page curl, between 0.0 and 1.0 + * + * Sets the period of the page curling, between 0.0 (no curling) + * and 1.0 (fully curled) + * + * Since: 1.4 + */ +void +clutter_page_turn_effect_set_period (ClutterPageTurnEffect *effect, + gdouble period) +{ + g_return_if_fail (CLUTTER_IS_PAGE_TURN_EFFECT (effect)); + g_return_if_fail (period >= 0.0 && period <= 1.0); + + effect->period = period; + + clutter_deform_effect_invalidate (CLUTTER_DEFORM_EFFECT (effect)); + + g_object_notify (G_OBJECT (effect), "period"); +} + +/** + * clutter_page_turn_effect_get_period: + * @effect: a #ClutterPageTurnEffect + * + * Retrieves the value set using clutter_page_turn_effect_get_period() + * + * Return value: the period of the page curling + * + * Since: 1.4 + */ +gdouble +clutter_page_turn_effect_get_period (ClutterPageTurnEffect *effect) +{ + g_return_val_if_fail (CLUTTER_IS_PAGE_TURN_EFFECT (effect), 0.0); + + return effect->period; +} + +/** + * clutter_page_turn_effect_set_angle: + * @effect: #ClutterPageTurnEffect + * @angle: the angle of the page curl, in degrees + * + * Sets the angle of the page curling, in degrees + * + * Since: 1.4 + */ +void +clutter_page_turn_effect_set_angle (ClutterPageTurnEffect *effect, + gdouble angle) +{ + g_return_if_fail (CLUTTER_IS_PAGE_TURN_EFFECT (effect)); + g_return_if_fail (angle >= 0.0 && angle <= 360.0); + + effect->angle = angle; + + clutter_deform_effect_invalidate (CLUTTER_DEFORM_EFFECT (effect)); + + g_object_notify (G_OBJECT (effect), "angle"); +} + +/** + * clutter_page_turn_effect_get_angle: + * @effect: a #ClutterPageTurnEffect: + * + * Retrieves the value set using clutter_page_turn_effect_get_angle() + * + * Return value: the angle of the page curling + * + * Since: 1.4 + */ +gdouble +clutter_page_turn_effect_get_angle (ClutterPageTurnEffect *effect) +{ + g_return_val_if_fail (CLUTTER_IS_PAGE_TURN_EFFECT (effect), 0.0); + + return effect->angle; +} + +/** + * clutter_page_turn_effect_set_radius: + * @effect: a #ClutterPageTurnEffect: + * @radius: the radius of the page curling, in pixels + * + * Sets the radius of the page curling + * + * Since: 1.4 + */ +void +clutter_page_turn_effect_set_radius (ClutterPageTurnEffect *effect, + gfloat radius) +{ + g_return_if_fail (CLUTTER_IS_PAGE_TURN_EFFECT (effect)); + + effect->radius = radius; + + clutter_deform_effect_invalidate (CLUTTER_DEFORM_EFFECT (effect)); + + g_object_notify (G_OBJECT (effect), "radius"); +} + +/** + * clutter_page_turn_effect_get_radius: + * @effect: a #ClutterPageTurnEffect + * + * Retrieves the value set using clutter_page_turn_effect_set_radius() + * + * Return value: the radius of the page curling + * + * Since: 1.4 + */ +gfloat +clutter_page_turn_effect_get_radius (ClutterPageTurnEffect *effect) +{ + g_return_val_if_fail (CLUTTER_IS_PAGE_TURN_EFFECT (effect), 0.0); + + return effect->radius; +} diff --git a/clutter/clutter-page-turn-effect.h b/clutter/clutter-page-turn-effect.h new file mode 100644 index 000000000..ca95fb824 --- /dev/null +++ b/clutter/clutter-page-turn-effect.h @@ -0,0 +1,71 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2010 Intel Corporation. + * + * 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 . + * + * Author: + * Emmanuele Bassi + * + * Based on MxDeformPageTurn, written by: + * Chris Lord + */ + +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __CLUTTER_PAGE_TURN_EFFECT_H__ +#define __CLUTTER_PAGE_TURN_EFFECT_H__ + +#include + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_PAGE_TURN_EFFECT (clutter_page_turn_effect_get_type ()) +#define CLUTTER_PAGE_TURN_EFFECT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_PAGE_TURN_EFFECT, ClutterPageTurnEffect)) +#define CLUTTER_IS_PAGE_TURN_EFFECT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_PAGE_TURN_EFFECT)) + +/** + * ClutterPageTurnEffect: + * + * ClutterPageTurnEffect is an opaque structure + * whose members can only be accessed using the provided API + * + * Since: 1.4 + */ +typedef struct _ClutterPageTurnEffect ClutterPageTurnEffect; + +GType clutter_page_turn_effect_get_type (void) G_GNUC_CONST; + +ClutterEffect *clutter_page_turn_effect_new (gdouble period, + gdouble angle, + gfloat radius); + +void clutter_page_turn_effect_set_period (ClutterPageTurnEffect *effect, + gdouble period); +gdouble clutter_page_turn_effect_get_period (ClutterPageTurnEffect *effect); +void clutter_page_turn_effect_set_angle (ClutterPageTurnEffect *effect, + gdouble angle); +gdouble clutter_page_turn_effect_get_angle (ClutterPageTurnEffect *effect); +void clutter_page_turn_effect_set_radius (ClutterPageTurnEffect *effect, + gfloat radius); +gfloat clutter_page_turn_effect_get_radius (ClutterPageTurnEffect *effect); + +G_END_DECLS + +#endif /* __CLUTTER_PAGE_TURN_EFFECT_H__ */ diff --git a/clutter/clutter.h b/clutter/clutter.h index 70c8fa37b..3f64f0945 100644 --- a/clutter/clutter.h +++ b/clutter/clutter.h @@ -81,6 +81,7 @@ #include "clutter-media.h" #include "clutter-model.h" #include "clutter-offscreen-effect.h" +#include "clutter-page-turn-effect.h" #include "clutter-path.h" #include "clutter-rectangle.h" #include "clutter-score.h" diff --git a/tests/interactive/test-drag.c b/tests/interactive/test-drag.c index 08197c319..7fda1a552 100644 --- a/tests/interactive/test-drag.c +++ b/tests/interactive/test-drag.c @@ -2,6 +2,28 @@ #include #include +static gboolean +on_enter (ClutterActor *actor, + ClutterEvent *event) +{ + clutter_actor_animate (actor, CLUTTER_LINEAR, 150, + "@effects.curl.period", 0.25, + NULL); + + return FALSE; +} + +static gboolean +on_leave (ClutterActor *actor, + ClutterEvent *event) +{ + clutter_actor_animate (actor, CLUTTER_LINEAR, 150, + "@effects.curl.period", 0.0, + NULL); + + return FALSE; +} + static void on_drag_begin (ClutterDragAction *action, ClutterActor *actor, @@ -156,6 +178,8 @@ test_drag_main (int argc, char *argv[]) clutter_actor_set_position (handle, (800 - 128) / 2, (600 - 128) / 2); clutter_actor_set_reactive (handle, TRUE); clutter_container_add_actor (CLUTTER_CONTAINER (stage), handle); + g_signal_connect (handle, "enter-event", G_CALLBACK (on_enter), NULL); + g_signal_connect (handle, "leave-event", G_CALLBACK (on_leave), NULL); action = clutter_drag_action_new (); clutter_drag_action_set_drag_threshold (CLUTTER_DRAG_ACTION (action), @@ -169,6 +193,7 @@ test_drag_main (int argc, char *argv[]) clutter_actor_add_action (handle, action); clutter_actor_add_effect_with_name (handle, "disable", clutter_desaturate_effect_new (0.0)); + clutter_actor_add_effect_with_name (handle, "curl", clutter_page_turn_effect_new (0.0, 135.0, 12.0)); clutter_actor_show (stage); From 7343c66482f2a7a94b442a640a16d5107be65fc2 Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Thu, 10 Jun 2010 18:51:22 +0100 Subject: [PATCH 5/5] docs: Add DeformEffect and PageTurnEffect to the API reference --- doc/reference/clutter/clutter-docs.xml.in | 2 ++ doc/reference/clutter/clutter-sections.txt | 40 ++++++++++++++++++++++ doc/reference/clutter/clutter.types | 2 ++ 3 files changed, 44 insertions(+) diff --git a/doc/reference/clutter/clutter-docs.xml.in b/doc/reference/clutter/clutter-docs.xml.in index 2a6b7065b..6433f790e 100644 --- a/doc/reference/clutter/clutter-docs.xml.in +++ b/doc/reference/clutter/clutter-docs.xml.in @@ -106,6 +106,8 @@ + + diff --git a/doc/reference/clutter/clutter-sections.txt b/doc/reference/clutter/clutter-sections.txt index 9f1b7436f..79d1d0ed2 100644 --- a/doc/reference/clutter/clutter-sections.txt +++ b/doc/reference/clutter/clutter-sections.txt @@ -2401,3 +2401,43 @@ CLUTTER_IS_DESATURATE_EFFECT clutter_desaturate_effect_get_type + +
+clutter-deform-effect +ClutterDeformEffect +ClutterDeformEffectClass +clutter_deform_effect_set_back_material +clutter_deform_effect_get_back_material +clutter_deform_effect_set_n_tiles +clutter_deform_effect_get_n_tiles + +clutter_deform_effect_invalidate + +CLUTTER_TYPE_DEFORM_EFFECT +CLUTTER_DEFORM_EFFECT +CLUTTER_DEFORM_EFFECT_CLASS +CLUTTER_IS_DEFORM_EFFECT +CLUTTER_IS_DEFORM_EFFECT_CLASS +CLUTTER_DEFORM_EFFECT_GET_CLASS + +ClutterDeformEffectPrivate +clutter_deform_effect_get_type +
+ +
+clutter-page-turn-effect +ClutterPageTurnEffect +clutter_page_turn_effect_new +clutter_page_turn_effect_set_period +clutter_page_turn_effect_get_period +clutter_page_turn_effect_set_angle +clutter_page_turn_effect_get_angle +clutter_page_turn_effect_set_radius +clutter_page_turn_effect_get_radius + +CLUTTER_TYPE_PAGE_TURN_EFFECT +CLUTTER_PAGE_TURN_EFFECT +CLUTTER_IS_PAGE_TURN_EFFECT + +clutter_page_turn_effect_get_type +
diff --git a/doc/reference/clutter/clutter.types b/doc/reference/clutter/clutter.types index 517b72f32..9e22d5c38 100644 --- a/doc/reference/clutter/clutter.types +++ b/doc/reference/clutter/clutter.types @@ -27,6 +27,7 @@ clutter_click_action_get_type clutter_clone_get_type clutter_colorize_effect_get_type clutter_constraint_get_type +clutter_deform_effect_get_type clutter_desaturate_effect_get_type clutter_device_manager_get_type clutter_drag_action_get_type @@ -43,6 +44,7 @@ clutter_media_get_type clutter_model_get_type clutter_model_iter_get_type clutter_offscreen_effect_get_type +clutter_page_turn_effect_get_type clutter_path_get_type clutter_rectangle_get_type clutter_score_get_type