diff --git a/doc/cookbook/Makefile.am b/doc/cookbook/Makefile.am
index c567cbdeb..5c70e4dfe 100644
--- a/doc/cookbook/Makefile.am
+++ b/doc/cookbook/Makefile.am
@@ -37,6 +37,8 @@ HTML_FILES = $(top_builddir)/doc/cookbook/html/*.html
CSS_FILES = $(top_builddir)/doc/cookbook/html/*.css
IMAGE_FILES = \
$(srcdir)/images/clutter-logo.png \
+ $(srcdir)/images/effects-basic.png \
+ $(srcdir)/images/effects-basic-background.png \
$(srcdir)/images/effects-built-in.png \
$(srcdir)/images/effects-custom-deform.png \
$(srcdir)/images/effects-custom-deform-back-material.png \
diff --git a/doc/cookbook/effects.xml b/doc/cookbook/effects.xml
index 2688bc941..d6c02955d 100644
--- a/doc/cookbook/effects.xml
+++ b/doc/cookbook/effects.xml
@@ -245,6 +245,543 @@ clutter_actor_add_effect (texture, effect);
+
+ Changing an actor's paint sequence using
+ ClutterEffect
+
+
+ Problem
+
+ You want to paint on top of or under an actor in a generic
+ way, without editing the actor's paint()
+ implementation. Example use cases are:
+
+
+
+ Adding a border on top of an actor.
+
+
+ Drawing a background for an actor.
+
+
+
+ A quick way to achieve the same thing (though not
+ readily portable between actors) is to connect a callback
+ before or after an actor's paint signal.
+ See this recipe for
+ more details. However, using a ClutterEffect
+ implementation, as explained in this recipe, is the preferred
+ approach.
+
+
+
+ Solution
+
+ Create a subclass of the ClutterEffect abstract
+ class; then implement the pre_paint() and/or
+ post_paint() virtual functions. When the
+ effect is applied to an actor, these functions will paint
+ before and after the actor's own paint()
+ implementation.
+
+
+ For this solution, we implement a simple
+ CbBackgroundEffect which draws a gray rectangle
+ under an actor. The full source is in
+ this
+ section. To keep it simple, the effect has no properties
+ and isn't configurable (the background is always gray); see the
+ border
+ effect for a more detailed implementation with GObject
+ trimmings.
+
+
+ First, create a ClutterEffect subclass. This
+ requires the trappings of a GObject class; in particular,
+ it needs a private struct to hold the effect's state. This
+ should include any CoglMaterials,
+ CoglColors or other private member variables
+ you intend to use to draw the effect.
+
+ In the case of the background effect, we have a background
+ CoglMaterial and a CoglColor for that
+ material:
+
+
+
+struct _CbBackgroundEffectPrivate
+{
+ CoglMaterial *background;
+ CoglColor *color;
+};
+
+
+
+ In the init() function for objects of
+ your class, create any Cogl resources which you need to draw the
+ effect. In the case of the background effect,
+ we need to create the CoglMaterial and
+ CoglColor for the private struct:
+
+
+
+priv = CB_BACKGROUND_EFFECT_GET_PRIVATE (self);
+
+ /* create the background material */
+ priv->background = cogl_material_new ();
+
+ /* gray color for filling the background material */
+ priv->color = cogl_color_new ();
+ cogl_color_init_from_4ub (priv->color, 122, 122, 122, 255);
+
+ /* set the color on the material; NB this isn't configurable
+ * for this effect, and is always gray
+ */
+ cogl_material_set_color (priv->background, priv->color);
+}
+]]>
+
+
+
+ Optionally, you can create GObject properties for
+ the class, if you want a configurable effect: see
+ this
+ section for details.
+
+ The dispose() function for your effect
+ should clean up any Cogl resources:
+
+
+
+priv;
+
+ if (priv->background != COGL_INVALID_HANDLE)
+ {
+ cogl_handle_unref (priv->background);
+ priv->background = COGL_INVALID_HANDLE;
+ }
+
+ if (priv->color != NULL)
+ {
+ cogl_color_free (priv->color);
+ priv->color = NULL;
+ }
+
+ G_OBJECT_CLASS (cb_background_effect_parent_class)->dispose (gobject);
+}
+]]>
+
+
+
+ Now, the important part: implement pre_paint()
+ and/or post_paint(), using Cogl to draw on the
+ material(s) set up for the effect. In these functions, you should also
+ check whether the effect is enabled before drawing.
+
+ For the background effect, we implement pre_paint(),
+ to draw a gray rectangle under the actor:
+
+
+
+priv;
+
+ /* get the associated actor's dimensions */
+ actor = clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (self));
+ clutter_actor_get_size (actor, &width, &height);
+
+ /* draw a Cogl rectangle in the background using the default color */
+ cogl_set_source (priv->background);
+
+ /* the rectangle has the same dimensions as the actor */
+ cogl_rectangle (0, 0, width, height);
+
+ return TRUE;
+}
+]]>
+
+
+
+ Now, in the init() function for the
+ effect class, assign your implementations to the
+ virtual methods of the ClutterEffect abstract class:
+
+
+
+pre_paint = cb_background_effect_pre_paint;
+ gobject_class->dispose = cb_background_effect_dispose;
+
+ g_type_class_add_private (klass, sizeof (CbBackgroundEffectPrivate));
+}
+]]>
+
+
+
+ If you intend to make your effect reusable, provide
+ a public constructor (as is done for the example effects in this
+ recipe):
+
+
+
+ClutterEffect *
+cb_background_effect_new ()
+{
+ return g_object_new (CB_TYPE_BACKGROUND_EFFECT,
+ NULL);
+}
+
+
+
+ The effect is now ready to be used. The application code
+ for applying your effect to an actor is the same as for any
+ other effect:
+
+
+
+ClutterActor *texture;
+ClutterEffect *background_effect;
+
+/* ...initialize texture, load image file etc... */
+
+/* create a gray background effect */
+background_effect = cb_background_effect_new ();
+
+/* apply the effect to the actor */
+clutter_actor_add_effect (texture, background_effect);
+
+
+
+ Below is an example of applying this effect to a texture loaded
+ with an image; the image has a transparent background, so the
+ background is visible through it. The screenshot is from
+ the example
+ application:
+
+
+
+
+
+
+
+ Applying CbBackgroundEffect
+ to a texture loaded with an image that has a transparent
+ background
+
+
+
+
+
+
+
+ Discussion
+
+ A basic ClutterEffect is particularly useful for
+ amending the appearance of an actor on the fly: for example,
+ to highlight an actor in response to a button presses. This
+ could be done by creating a custom widget
+ whose appearance could be toggled. But what if you wanted to make
+ an arbitrary actor's appearance "togglable"? A generic effect
+ in the style of the border effect in this recipe can be applied
+ to any actor, and easily toggled by enabling/disabling the
+ effect.
+
+ ClutterEffect works best where
+ you want to overlay or underlay the actor with Cogl paths or
+ primitives, without changing the actor's geometry. If you want
+ to do complicated geometry transformations, or other subtle
+ manipulations of an actor's appearance, it is better to use
+ a ClutterEffect subclass like
+ ClutterOffscreenEffect, ClutterDeformEffect,
+ or ClutterShaderEffect.
+
+ In a similar vein, when a ClutterEffect is
+ applied to an actor, the effect shouldn't paint outside the actor's
+ allocation. However, if the effect provides a
+ get_paint_volume() implementation which
+ returns a volume larger than the actor's allocation, the effect
+ can paint anywhere within that volume. Though
+ in most cases, creating a custom paint volume is only going to be
+ useful for offscreen effects, where you are changing the
+ actor's geometry.
+
+
+ Effect properties
+
+ If your effect has GObject properties, you should
+ ensure that an actor associated with the effect is queued
+ for a redraw when those properties change. (You only need to
+ do this for properties which change the effect's appearance;
+ but this is likely to include most of an effect's properties.)
+
+ In most cases, you're likely define standard GObject
+ properties for the class; for example,
+ CbBorderEffect
+ defines a width property like this:
+
+
+
+
+
+
+
+ It also defines a standard GObject
+ set_property() function for
+ width:
+
+
+
+
+
+
+
+ Note that this calls
+ cb_border_effect_set_width(), which is
+ also exposed in the public API. This is where the
+ width member variable is actually set in
+ the private struct; and also where the redraw for the actor
+ associated with the effect should be queued:
+
+
+
+width = width;
+
+ /* the property has been updated, so queue a redraw of the actor (if set) */
+ cb_border_effect_update (self);
+}
+]]>
+
+
+
+ Any other property setters which affect the associated
+ actor's appearance (i.e. color in the case of
+ CbBorderEffect) should also call the update
+ function after setting the property.
+
+
+ If your effect exposes GObject properties in this way,
+ it can also be animated with the Clutter animation API as usual.
+ For example, you could animate the border effect in this recipe
+ so that the border gradually becomes thinner or thicker.
+
+
+
+
+
+
+
+ Full example
+
+ The example application applies two effects to a
+ group of ClutterTextures:
+
+
+
+ A CbBackgroundEffect which draws a gray
+ background under each actor. The effect is implemented in
+ a header
+ file and a C
+ code file.
+
+
+ A CbBorderEffect which draws a
+ red border on top of an actor; this is toggled by clicking
+ on the actor. The effect is implemented in
+ a header
+ file and a C
+ code file.
+
+
+
+ The application
+ creates textures from the file paths specified
+ on the command line then applies both of these effects to
+ each texture. In the case of the CbBorderEffect,
+ a 5 pixel red border is applied; this is also disabled by default,
+ and enabled when a texture is clicked.
+
+ Here is an example of the output when the application is loaded
+ with four images:
+
+
+
+
+
+
+
+ Applying CbBackgroundEffect
+ and a togglable CbBorderEffect
+ to a several textures
+
+
+
+
+
+ CbBackgroundEffect
+
+
+ cb-background-effect.h (header file)
+
+
+ a code sample should be here... but isn't
+
+
+
+
+
+ cb-background-effect.c (code file)
+
+
+ a code sample should be here... but isn't
+
+
+
+
+
+
+ CbBorderEffect
+
+ This is a more sophisticated effect with configurable
+ border color and width.
+
+
+ cb-border-effect.h (header file)
+
+
+ a code sample should be here... but isn't
+
+
+
+
+
+ cb-border-effect.c (code file)
+
+
+ a code sample should be here... but isn't
+
+
+
+
+
+
+ Application
+
+
+ Application which applies CbBorderEffect
+ and CbBackgroundEffect to a group of
+ ClutterTextures.
+
+
+ a code sample should be here... but isn't
+
+
+
+
+
+
+
+
+
Creating and animating a custom ClutterDeformEffect
diff --git a/doc/cookbook/images/effects-basic-background.png b/doc/cookbook/images/effects-basic-background.png
new file mode 100644
index 000000000..737affe91
Binary files /dev/null and b/doc/cookbook/images/effects-basic-background.png differ
diff --git a/doc/cookbook/images/effects-basic.png b/doc/cookbook/images/effects-basic.png
new file mode 100644
index 000000000..38c36a258
Binary files /dev/null and b/doc/cookbook/images/effects-basic.png differ