## ClutterEffect

ClutterEffect — Base class for actor effects

## Synopsis

    struct              ClutterEffect;
    struct              ClutterEffectClass;

## Object Hierarchy

      GObject
       +----GInitiallyUnowned
             +----ClutterActorMeta
                   +----ClutterEffect
                         +----ClutterOffscreenEffect

## Description

The ClutterEffect class provides a default type and API for creating effects for generic actors.

Effects are a ClutterActorMeta sub-class that modify the way an actor is painted in a way that is not part of the actor's implementation.

Effects should be the preferred way to affect the paint sequence of an actor without sub-classing the actor itself and overriding the "paint" virtual function.

### Implementing a ClutterEffect

Creating a sub-class of ClutterEffect requires the implementation of two virtual functions:

- ``pre_paint()``, which is called before painting the ClutterActor.
- ``post_paint()``, which is called after painting the ClutterActor.

The ``pre_paint()`` function should be used to set up the ClutterEffect right before the ClutterActor's paint 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 handler to the "paint" signal, while the ``post_paint()`` phase could be seen as a custom handler to the "paint" signal connected using `g_signal_connect_after()`.

Example 3. 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 ``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.

     typedef struct {
       ClutterEffect parent_instance;

       CoglHandle rect_1;
       CoglHandle rect_2;
     } MyEffect;

     typedef struct _ClutterEffectClass MyEffectClass;

     G_DEFINE_TYPE (MyEffect, my_effect, CLUTTER_TYPE_EFFECT);

     static void
     my_effect_set_actor (ClutterActorMeta *meta,
                          ClutterActor     *actor)
     {
       MyEffect *self = MY_EFFECT (meta);

       /* Clear the previous state */
       if (self->rect_1)
         {
           cogl_handle_unref (self->rect_1);
           self->rect_1 = NULL;
         }

       if (self->rect_2)
         {
           cogl_handle_unref (self->rect_2);
           self->rect_2 = NULL;
         }

       /* Maintain a pointer to the actor *
       self->actor = actor;

       /* If we've been detached by the actor then we should
        * just bail out here
        */
       if (self->actor == NULL)
         return;

       /* Create a red material */
       self->rect_1 = cogl_material_new ();
       cogl_material_set_color4f (self->rect_1, 1.0, 0.0, 0.0, 1.0);

       /* Create a green material */
       self->rect_2 = cogl_material_new ();
       cogl_material_set_color4f (self->rect_2, 0.0, 1.0, 0.0, 1.0);
     }

     static gboolean
     my_effect_pre_paint (ClutterEffect *effect)
     {
       MyEffect *self = MY_EFFECT (effect);
       gfloat width, height;

       /* If we were disabled we don't need to paint anything */
       if (!clutter_actor_meta_get_enabled (CLUTTER_ACTOR_META (effect)))
         return FALSE;

       clutter_actor_get_size (self->actor, &width, &height);

       /* Paint the first rectangle in the upper left quadrant */
       cogl_set_source (self->rect_1);
       cogl_rectangle (0, 0, width / 2, height / 2);

       return TRUE;
     }

     static void
     my_effect_post_paint (ClutterEffect *effect)
     {
       MyEffect *self = MY_EFFECT (effect);
       gfloat width, height;

       clutter_actor_get_size (self->actor, &width, &height);

       /* Paint the second rectangle in the lower right quadrant */
       cogl_set_source (self->rect_2);
       cogl_rectangle (width / 2, height / 2, width, height);
     }

     static void
     my_effect_class_init (MyEffectClass *klass)
     {
       ClutterActorMetaClas *meta_class = CLUTTER_ACTOR_META_CLASS (klass);

       meta_class->set_actor = my_effect_set_actor;

       klass->pre_paint = my_effect_pre_paint;
       klass->post_paint = my_effect_post_paint;
     }

ClutterEffect is available since Clutter 1.4

## Details

### struct ClutterEffect

    struct ClutterEffect;

The ClutterEffect structure contains only private data and should be accessed using the provided API

Since 1.4

### struct ClutterEffectClass

    struct ClutterEffectClass {
      gboolean (* pre_paint)  (ClutterEffect *effect);
      void     (* post_paint) (ClutterEffect *effect);
    };

The ClutterEffectClass structure contains only private data

`pre_paint` () | virtual function
`post_paint` () | virtual function

Since 1.4