4 * An OpenGL based 'interactive canvas' library.
6 * Copyright (C) 2010 Intel Corporation.
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
22 * Emmanuele Bassi <ebassi@linux.intel.com>
24 * Based on MxDeformPageTurn, written by:
25 * Chris Lord <chris@linux.intel.com>
29 * SECTION:clutter-page-turn-effect
30 * @Title: ClutterPageTurnEffect
31 * @Short_Description: A page turning effect
33 * A simple page turning effect
35 * #ClutterPageTurnEffect is available since Clutter 1.4
44 #include "clutter-page-turn-effect.h"
46 #include "clutter-debug.h"
47 #include "clutter-private.h"
49 #define CLUTTER_PAGE_TURN_EFFECT_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), CLUTTER_TYPE_PAGE_TURN_EFFECT, ClutterPageTurnEffectClass))
50 #define CLUTTER_IS_PAGE_TURN_EFFECT_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), CLUTTER_TYPE_PAGE_TURN_EFFECT))
51 #define CLUTTER_PAGE_TURN_EFFECT_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), CLUTTER_TYPE_PAGE_TURN_EFFECT, ClutterPageTurnEffectClass))
53 struct _ClutterPageTurnEffect
55 ClutterDeformEffect parent_instance;
63 struct _ClutterPageTurnEffectClass
65 ClutterDeformEffectClass parent_class;
79 static GParamSpec *obj_props[PROP_LAST];
81 G_DEFINE_TYPE (ClutterPageTurnEffect,
82 clutter_page_turn_effect,
83 CLUTTER_TYPE_DEFORM_EFFECT);
86 clutter_page_turn_effect_deform_vertex (ClutterDeformEffect *effect,
89 CoglTextureVertex *vertex)
91 ClutterPageTurnEffect *self = CLUTTER_PAGE_TURN_EFFECT (effect);
92 gfloat cx, cy, rx, ry, radians, turn_angle;
95 if (self->period == 0.0)
98 radians = self->angle / (180.0f / G_PI);
100 /* Rotate the point around the centre of the page-curl ray to align it with
103 cx = (1.f - self->period) * width;
104 cy = (1.f - self->period) * height;
106 rx = ((vertex->x - cx) * cos (- radians))
107 - ((vertex->y - cy) * sin (- radians))
109 ry = ((vertex->x - cx) * sin (- radians))
110 + ((vertex->y - cy) * cos (- radians));
113 if (rx > self->radius * -2.0f)
115 /* Calculate the curl angle as a function from the distance of the curl
116 * ray (i.e. the page crease)
118 turn_angle = (rx / self->radius * G_PI_2) - G_PI_2;
119 shade = (sin (turn_angle) * 96.0f) + 159.0f;
121 /* Add a gradient that makes it look like lighting and hides the switch
124 cogl_color_init_from_4ub (&vertex->color, shade, shade, shade, 0xff);
129 /* Make the curl radius smaller as more circles are formed (stops
130 * z-fighting and looks cool). Note that 10 is a semi-arbitrary
131 * number here - divide it by two and it's the amount of space
132 * between curled layers of the texture, in pixels.
136 small_radius = self->radius
137 - MIN (self->radius, (turn_angle * 10) / G_PI);
139 /* Calculate a point on a cylinder (maybe make this a cone at some
140 * point) and rotate it by the specified angle.
142 rx = (small_radius * cos (turn_angle)) + self->radius;
144 vertex->x = (rx * cos (radians)) - (ry * sin (radians)) + cx;
145 vertex->y = (rx * sin (radians)) + (ry * cos (radians)) + cy;
146 vertex->z = (small_radius * sin (turn_angle)) + self->radius;
151 clutter_page_turn_effect_set_property (GObject *gobject,
156 ClutterPageTurnEffect *effect = CLUTTER_PAGE_TURN_EFFECT (gobject);
161 clutter_page_turn_effect_set_period (effect, g_value_get_double (value));
165 clutter_page_turn_effect_set_angle (effect, g_value_get_double (value));
169 clutter_page_turn_effect_set_radius (effect, g_value_get_float (value));
173 G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
179 clutter_page_turn_effect_get_property (GObject *gobject,
184 ClutterPageTurnEffect *effect = CLUTTER_PAGE_TURN_EFFECT (gobject);
189 g_value_set_double (value, effect->period);
193 g_value_set_double (value, effect->angle);
197 g_value_set_float (value, effect->radius);
201 G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
207 clutter_page_turn_effect_class_init (ClutterPageTurnEffectClass *klass)
209 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
210 ClutterDeformEffectClass *deform_class = CLUTTER_DEFORM_EFFECT_CLASS (klass);
213 gobject_class->set_property = clutter_page_turn_effect_set_property;
214 gobject_class->get_property = clutter_page_turn_effect_get_property;
217 * ClutterPageTurnEffect:period:
219 * The period of the page turn, between 0.0 (no curling) and
224 pspec = g_param_spec_double ("period",
226 "The period of the page turn",
229 CLUTTER_PARAM_READWRITE);
230 obj_props[PROP_PERIOD] = pspec;
231 g_object_class_install_property (gobject_class, PROP_PERIOD, pspec);
234 * ClutterPageTurnEffect:angle:
236 * The angle of the page rotation, in degrees, between 0.0 and 360.0
240 pspec = g_param_spec_double ("angle",
242 "The angle of the page rotation, in degrees",
245 CLUTTER_PARAM_READWRITE);
246 obj_props[PROP_ANGLE] = pspec;
247 g_object_class_install_property (gobject_class, PROP_ANGLE, pspec);
250 * ClutterPageTurnEffect:radius:
252 * The radius of the page curl, in pixels
256 pspec = g_param_spec_float ("radius",
258 "The radius of the page curl",
259 -G_MAXFLOAT, G_MAXFLOAT,
261 CLUTTER_PARAM_READWRITE);
262 obj_props[PROP_RADIUS] = pspec;
263 g_object_class_install_property (gobject_class, PROP_RADIUS, pspec);
265 deform_class->deform_vertex = clutter_page_turn_effect_deform_vertex;
269 clutter_page_turn_effect_init (ClutterPageTurnEffect *self)
273 self->radius = 24.0f;
277 * clutter_page_turn_effect_new:
278 * @period: the period of the page curl, between 0.0 and 1.0
279 * @angle: the angle of the page curl, between 0.0 and 360.0
280 * @radius: the radius of the page curl, in pixels
282 * Creates a new #ClutterPageTurnEffect instance with the given parameters
284 * Return value: the newly created #ClutterPageTurnEffect
289 clutter_page_turn_effect_new (gdouble period,
293 g_return_val_if_fail (period >= 0.0 && period <= 1.0, NULL);
294 g_return_val_if_fail (angle >= 0.0 && angle <= 360.0, NULL);
296 return g_object_new (CLUTTER_TYPE_PAGE_TURN_EFFECT,
304 * clutter_page_turn_effect_set_period:
305 * @effect: a #ClutterPageTurnEffect
306 * @period: the period of the page curl, between 0.0 and 1.0
308 * Sets the period of the page curling, between 0.0 (no curling)
309 * and 1.0 (fully curled)
314 clutter_page_turn_effect_set_period (ClutterPageTurnEffect *effect,
317 g_return_if_fail (CLUTTER_IS_PAGE_TURN_EFFECT (effect));
318 g_return_if_fail (period >= 0.0 && period <= 1.0);
320 effect->period = period;
322 clutter_deform_effect_invalidate (CLUTTER_DEFORM_EFFECT (effect));
324 g_object_notify_by_pspec (G_OBJECT (effect), obj_props[PROP_PERIOD]);
328 * clutter_page_turn_effect_get_period:
329 * @effect: a #ClutterPageTurnEffect
331 * Retrieves the value set using clutter_page_turn_effect_get_period()
333 * Return value: the period of the page curling
338 clutter_page_turn_effect_get_period (ClutterPageTurnEffect *effect)
340 g_return_val_if_fail (CLUTTER_IS_PAGE_TURN_EFFECT (effect), 0.0);
342 return effect->period;
346 * clutter_page_turn_effect_set_angle:
347 * @effect: #ClutterPageTurnEffect
348 * @angle: the angle of the page curl, in degrees
350 * Sets the angle of the page curling, in degrees
355 clutter_page_turn_effect_set_angle (ClutterPageTurnEffect *effect,
358 g_return_if_fail (CLUTTER_IS_PAGE_TURN_EFFECT (effect));
359 g_return_if_fail (angle >= 0.0 && angle <= 360.0);
361 effect->angle = angle;
363 clutter_deform_effect_invalidate (CLUTTER_DEFORM_EFFECT (effect));
365 g_object_notify_by_pspec (G_OBJECT (effect), obj_props[PROP_ANGLE]);
369 * clutter_page_turn_effect_get_angle:
370 * @effect: a #ClutterPageTurnEffect:
372 * Retrieves the value set using clutter_page_turn_effect_get_angle()
374 * Return value: the angle of the page curling
379 clutter_page_turn_effect_get_angle (ClutterPageTurnEffect *effect)
381 g_return_val_if_fail (CLUTTER_IS_PAGE_TURN_EFFECT (effect), 0.0);
383 return effect->angle;
387 * clutter_page_turn_effect_set_radius:
388 * @effect: a #ClutterPageTurnEffect:
389 * @radius: the radius of the page curling, in pixels
391 * Sets the radius of the page curling
396 clutter_page_turn_effect_set_radius (ClutterPageTurnEffect *effect,
399 g_return_if_fail (CLUTTER_IS_PAGE_TURN_EFFECT (effect));
401 effect->radius = radius;
403 clutter_deform_effect_invalidate (CLUTTER_DEFORM_EFFECT (effect));
405 g_object_notify_by_pspec (G_OBJECT (effect), obj_props[PROP_RADIUS]);
409 * clutter_page_turn_effect_get_radius:
410 * @effect: a #ClutterPageTurnEffect
412 * Retrieves the value set using clutter_page_turn_effect_set_radius()
414 * Return value: the radius of the page curling
419 clutter_page_turn_effect_get_radius (ClutterPageTurnEffect *effect)
421 g_return_val_if_fail (CLUTTER_IS_PAGE_TURN_EFFECT (effect), 0.0);
423 return effect->radius;