diff --git a/clutter/Makefile.am b/clutter/Makefile.am index 560780363..6a7f789f1 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 \ @@ -117,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 \ @@ -182,6 +184,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 \ @@ -205,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-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-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. 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 */ 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 0b948af95..3f64f0945 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" @@ -80,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/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 49f5ceb44..873224f06 100644 --- a/doc/reference/clutter/clutter-sections.txt +++ b/doc/reference/clutter/clutter-sections.txt @@ -2403,3 +2403,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 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);