diff --git a/doc/cookbook/actors.xml b/doc/cookbook/actors.xml
index 4d3dcfd31..8c8a9a479 100644
--- a/doc/cookbook/actors.xml
+++ b/doc/cookbook/actors.xml
@@ -258,23 +258,23 @@ on_paint (ClutterActor *actor)
- Making an actor transparent by changing its opacity
+ Making an actor transparent by changing its opacity
-
- Problem
+
+ Problem
- You want an actor to be transparent so that other
- actors are visible through it.
-
+ You want an actor to be transparent so that other
+ actors are visible through it.
+
-
- Solution
+
+ Solution
- Change the actor's opacity so that
- it is partially (or even fully) transparent:
+ Change the actor's opacity so that
+ it is partially (or even fully) transparent:
-
-
+
+
/* 25% transparency */
clutter_actor_set_opacity (actor, 191.25);
@@ -283,126 +283,126 @@ clutter_actor_set_opacity (actor, 122.5);
/* completely transparent */
clutter_actor_set_opacity (actor, 0);
-
-
+
+
- Any actor covered or overlapped by the transparent actor
- should be visible through it; the Discussion section gives
- some examples of how visible you can expect the covered or
- overlapped actor to be.
+ Any actor covered or overlapped by the transparent actor
+ should be visible through it; the Discussion section gives
+ some examples of how visible you can expect the covered or
+ overlapped actor to be.
-
+
+
+
+ Discussion
+
+ Opacity is a property of every ClutterActor.
+ It is a float on a scale from 0 (invisible) to 255 (completely
+ opaque). Actors with 0 < opacity < 255
will
+ have a varying amount of solidity on the stage, so other actors
+ may be visible through them.
+
+ For example, below are 4 yellow rectangles overlapping
+ a white rectangle on a blue stage:
+
+
+
+
+
+
+
+ The effect of different opacities levels on
+ an actor's appearance
+
+
+
+
+ The rectangles have the following opacities:
+
+
+
+ top-left: 255
(0% transparency)
+
+
+ top-right: 191.25
(25% transparency)
+
+
+ bottom-right: 122.5
(50% transparency)
+
+
+ bottom-left: 61.25
(75% transparency)
+
+
+
+ Notice how both the stage and the white rectangle are
+ visible through the yellow rectangles.
+
+ As opacity is a property of every actor, it can
+ be animated like any other GObject property, using any of
+ the approaches in the animation API.
+
+ The following sections cover some other considerations
+ when working with actor opacity.
- Discussion
+ Container and color opacity
- Opacity is a property of every ClutterActor.
- It is a float on a scale from 0 (invisible) to 255 (completely
- opaque). Actors with 0 < opacity < 255
will
- have a varying amount of solidity on the stage, so other actors
- may be visible through them.
+ If a container has its opacity set, any children of the
+ container have their opacity combined with their parent's opacity.
+ For example, if a parent has an opacity of 122.5
+ (50% transparent) and the child also has an opacity of
+ 122.5
, the child's effective
+ opacity is 25% (opacity = 61.25
, and it is
+ 75% transparent).
- For example, below are 4 yellow rectangles overlapping
- a white rectangle on a blue stage:
+ To demonstrate the visual effect of this, here are
+ three rectangles with the same color but different opacity settings,
+ inside parents which also have different opacity settings:
+ fileref="images/actors-opacity-container-affects-opacity.png" />
- The effect of different opacities levels on
- an actor's appearance
+ How a container's opacity affects the opacity of
+ its children
- The rectangles have the following opacities:
-
- top-left: 255
(0% transparency)
+ The left-hand rectangle has opacity = 255
+ and is in a ClutterGroup with
+ opacity = 255
. This means it is fully opaque.
- top-right: 191.25
(25% transparency)
+ The middle rectangle has opacity = 255
+ and is in a ClutterGroup with
+ opacity = 122.5
. Notice that the parent opacity
+ makes the rectangle appear darker, as the stage colour is showing
+ through from behind.
- bottom-right: 122.5
(50% transparency)
-
-
- bottom-left: 61.25
(75% transparency)
+ The right-hand rectangle has opacity = 122.5
+ and is in a ClutterGroup with
+ opacity = 122.5
. Notice that the rectangle appears
+ to be even darker, as the stage colour is showing
+ through both the rectangle and its parent.
- Notice how both the stage and the white rectangle are
- visible through the yellow rectangles.
+ Similarly, ClutterColor also contains an
+ alpha property which governs the transparency
+ of the color. Where an actor can have a color set (e.g.
+ ClutterRectangle) the alpha value of the color also
+ affects the transparency of the actor, for example:
- As opacity is a property of every actor, it can
- be animated like any other GObject property, using any of
- the approaches in the animation API.
-
- The following sections cover some other considerations
- when working with actor opacity.
-
-
- Container and color opacity
-
- If a container has its opacity set, any children of the
- container have their opacity combined with their parent's opacity.
- For example, if a parent has an opacity of 122.5
- (50% transparent) and the child also has an opacity of
- 122.5
, the child's effective
- opacity is 25% (opacity = 61.25
, and it is
- 75% transparent).
-
- To demonstrate the visual effect of this, here are
- three rectangles with the same color but different opacity settings,
- inside parents which also have different opacity settings:
-
-
-
-
-
-
-
- How a container's opacity affects the opacity of
- its children
-
-
-
-
-
-
- The left-hand rectangle has opacity = 255
- and is in a ClutterGroup with
- opacity = 255
. This means it is fully opaque.
-
-
- The middle rectangle has opacity = 255
- and is in a ClutterGroup with
- opacity = 122.5
. Notice that the parent opacity
- makes the rectangle appear darker, as the stage colour is showing
- through from behind.
-
-
- The right-hand rectangle has opacity = 122.5
- and is in a ClutterGroup with
- opacity = 122.5
. Notice that the rectangle appears
- to be even darker, as the stage colour is showing
- through both the rectangle and its parent.
-
-
-
- Similarly, ClutterColor also contains an
- alpha property which governs the transparency
- of the color. Where an actor can have a color set (e.g.
- ClutterRectangle) the alpha value of the color also
- affects the transparency of the actor, for example:
-
-
-
+
+
-
-
+
+
-
+
-
- Depth and depth order
+
+ Depth and depth order
- Each actor has two more aspects which affect its
- apparent opacity:
+ Each actor has two more aspects which affect its
+ apparent opacity:
-
-
- An actor's depth can have an
- effect if the stage has fog (a depth cueing effect) turned on.
- As an actor's depth increases, the actor apparently "recedes" from
- view and gradually blends into the colour of the stage. This
- produces an effect similar to making the actor transparent.
- See the ClutterStage documentation for
- more details about fog.
+
+
+ An actor's depth can have an
+ effect if the stage has fog (a depth cueing effect) turned on.
+ As an actor's depth increases, the actor apparently "recedes" from
+ view and gradually blends into the colour of the stage. This
+ produces an effect similar to making the actor transparent.
+ See the ClutterStage documentation for
+ more details about fog.
- Depth also needs to be considered if you want
- one actor to be visible through another: the actor you want
- to see through a transparent actor must be "deeper" than (or at
- the same depth as) the transparent actor.
-
-
- The depth order governs how
- actors within a ClutterContainer implementation
- are placed with respect to each other.
+ Depth also needs to be considered if you want
+ one actor to be visible through another: the actor you want
+ to see through a transparent actor must be "deeper" than (or at
+ the same depth as) the transparent actor.
+
+
+ The depth order governs how
+ actors within a ClutterContainer implementation
+ are placed with respect to each other.
-
- Depth ordering is not the same thing as depth: depth
- ordering records relationships between actors at the same
- depth.
-
+
+ Depth ordering is not the same thing as depth: depth
+ ordering records relationships between actors at the same
+ depth.
+
- If you have two overlapping actors actorA
and
- actorB
in a container, and you want actorA
- (opaque) to be visible through actorB
(transparent),
- you should ensure that actorB
is "above" actorA
- in the depth ordering. You could do this as follows:
+ If you have two overlapping actors actorA
and
+ actorB
in a container, and you want actorA
+ (opaque) to be visible through actorB
(transparent),
+ you should ensure that actorB
is "above" actorA
+ in the depth ordering. You could do this as follows:
-
-
+
+
/*
- * raise actorB so it is above actorA in the depth order;
- * NB actorA and actorB both need to be in the same container
- * for this to work
- */
+* raise actorB so it is above actorA in the depth order;
+* NB actorA and actorB both need to be in the same container
+* for this to work
+*/
clutter_actor_raise (actorB, actorA);
-
-
+
+
- clutter_actor_raise(),
- clutter_actor_lower() and related
- ClutterActor functions set
- depth ordering on actors; see also ClutterContainer's
- clutter_container_raise_child() and
- clutter_container_lower_child()
- functions.
-
-
-
-
+ clutter_actor_raise(),
+ clutter_actor_lower() and related
+ ClutterActor functions set
+ depth ordering on actors; see also ClutterContainer's
+ clutter_container_raise_child() and
+ clutter_container_lower_child()
+ functions.
+
+
+
+
+
+ Creating an actor with a non-rectangular shape
+
+
+ Problem
+
+ You want to create a ClutterActor subclass,
+ but don't want it to be rectangular; for example, you want a
+ star-shaped actor.
+
+
+
+ Solution
+
+ Use Cogl primitives to draw the actor.
+
+ Below is an example of the pick and paint implementations for a
+ star-shaped StarActor class (an extension of
+ ClutterActor).
+
+ Like ClutterRectangle, it has a private
+ struct internally, which contains a ClutterColor
+ denoting the color it should be painted. This is used to set the Cogl
+ source color.
+
+
+
+priv->color;
+
+ clutter_actor_get_allocation_box (actor, &allocation);
+ clutter_actor_box_get_size (&allocation, &width, &height);
+
+ tmp_alpha = clutter_actor_get_paint_opacity (actor)
+ * color.alpha
+ / 255;
+
+ cogl_path_new ();
+
+ cogl_set_source_color4ub (color.red,
+ color.green,
+ color.blue,
+ tmp_alpha);
+
+ /* create and store a path describing a star */
+ cogl_path_move_to (width * 0.5, 0);
+ cogl_path_line_to (width, height * 0.75);
+ cogl_path_line_to (0, height * 0.75);
+ cogl_path_move_to (width * 0.5, height);
+ cogl_path_line_to (0, height * 0.25);
+ cogl_path_line_to (width, height * 0.25);
+ cogl_path_line_to (width * 0.5, height);
+
+ cogl_path_fill ();
+}
+
+static void
+star_actor_pick (ClutterActor *actor,
+ const ClutterColor *pick_color)
+{
+ if (!clutter_actor_should_pick_paint (actor))
+ return;
+
+ ClutterActorBox allocation = { 0, };
+ gfloat width, height;
+
+ clutter_actor_get_allocation_box (actor, &allocation);
+ clutter_actor_box_get_size (&allocation, &width, &height);
+
+ cogl_path_new ();
+
+ cogl_set_source_color4ub (pick_color->red,
+ pick_color->green,
+ pick_color->blue,
+ pick_color->alpha);
+
+ /* create and store a path describing a star */
+ cogl_path_move_to (width * 0.5, 0);
+ cogl_path_line_to (width, height * 0.75);
+ cogl_path_line_to (0, height * 0.75);
+ cogl_path_move_to (width * 0.5, height);
+ cogl_path_line_to (0, height * 0.25);
+ cogl_path_line_to (width, height * 0.25);
+ cogl_path_line_to (width * 0.5, height);
+
+ cogl_path_fill ();
+}
+]]>
+
+
+
+ If you need more information about how to implement your own
+ ClutterActor, see the Clutter reference
+ manual.
+
+ Note that the code in these two functions is virtually identical:
+ the Discussion section suggests how to remove this redundancy.
+
+
+
+ Discussion
+
+ The above is one approach to creating a non-rectangular
+ actor. But it's also possible to get a similar effect by
+ subclassing an existing actor (like ClutterRectangle)
+ and giving it a non-rectangular appearance. You could do this by
+ making the underlying rectangle transparent and then drawing on
+ top of it (e.g. using Cairo or Cogl).
+
+ However, if you then made such an actor reactive, events
+ like mouse button presses would be triggered from anywhere on
+ the underlying rectangle. This is true even if the visible part
+ of the actor only partially fills the rectangle (underneath, it's
+ still a rectangle).
+
+ The advantage of using Cogl paths is that the reactive area
+ of the actor is defined by the Cogl path. So if you have a
+ star-shaped actor, only clicks (or other events) directly on the
+ star will have any effect on it.
+
+
+ Cogl path coordinates
+
+ In the example shown, cogl_path_move_to()
+ and cogl_path_line_to() are used. These
+ take absolute x
and y
coordinates as
+ arguments, relative to the GL 'modelview' transform matrix; in
+ the case of an actor's paint implementation,
+ relative to the bounding box for the actor. So if an actor has
+ width and height of 50 pixels, and you used
+ cogl_move_to (25, 25) in its
+ paint implementation, the "pen"
+ moves to the centre of the actor, regardless of where the actor
+ is positioned on the stage. Similarly, using
+ cogl_path_line_to() creates a line segment
+ from the current pen position to the absolute coordinates
+ (x
, y
) specified.
+
+ The Cogl API also provides various "rel" variants of the path
+ functions (e.g. cogl_path_rel_line_to()), which
+ create path segments relative to the current pen position (i.e.
+ pen_x + x
, pen_y + y
).
+
+ It's important to note that the path isn't drawn until you
+ call cogl_path_stroke() (to draw the path segments)
+ or cogl_path_fill() (to fill the area enclosed by
+ the path). The path is cleared once it's been drawn.
+ Using the *_preserve variants of these functions draws
+ the path and retains it (so it could be drawn again).
+
+
+
+
+ Other Cogl primitives
+
+ Note that the Cogl primitives API provides other types of path
+ segment beyond straight lines that we didn't use here, including:
+
+
+
+ Bezier curves (cogl_path_curve_to())
+
+
+ Arcs (cogl_path_arc())
+
+
+ Polygons (cogl_path_polygon())
+
+
+ Rectangles (cogl_path_rectangle())
+
+
+ Rectangles with rounded corners
+ (cogl_path_round_rectangle())
+
+
+ Ellipses (cogl_path_ellipse())
+
+
+
+ If you need more flexibility than is available in the Cogl path
+ API, you can make direct use of the CoglVertexBuffer
+ API instead. This is a lower-level API, but could potentially
+ be used to draw more complex shapes.
+
+
+
+ Using ClutterPath to store the path
+
+ The disadvantage of the code above is that the paths are stored in two
+ places: once for pick, and once for
+ paint. It would make sense to store the
+ path in one place and reference it from both of these functions to
+ prevent duplication.
+
+ Clutter provides a ClutterPath API for storing
+ generic path descriptions. It can be used to describe paths
+ which translate to Cogl or Cairo paths, and can also be used to
+ describe animation paths.
+
+ We can use a ClutterPath instance stored
+ inside the actor to define the path for pick and
+ paint; then, inside those functions, we
+ translate the ClutterPath into Cogl path function calls
+ (NB ClutterPath is effectively a declarative method
+ for defining a path, while the Cogl path API is imperative).
+
+ First we add a path member to the private
+ struct for the StarActor class (using standard
+ GObject mechanisms). The init implementation for
+ StarActor creates an empty path:
+
+
+
+static void
+star_actor_init (StarActor *self)
+{
+ self->priv = STAR_ACTOR_GET_PRIVATE (self);
+
+ self->priv->path = clutter_path_new ();
+
+ clutter_actor_set_reactive (CLUTTER_ACTOR (self), TRUE);
+}
+
+
+
+ One consideration is that the path coordinates need to
+ fit inside the actor's bounding box. So as the actor's allocation
+ changes, path also needs to change. We can do this
+ by implementing allocate for the
+ StarActor class:
+
+
+
+priv->path;
+ gfloat width, height;
+
+ clutter_actor_box_get_size (box, &width, &height);
+
+ /* create and store a path describing a star */
+ clutter_path_clear (path);
+
+ clutter_path_add_move_to (path, width * 0.5, 0);
+ clutter_path_add_line_to (path, width, height * 0.75);
+ clutter_path_add_line_to (path, 0, height * 0.75);
+ clutter_path_add_move_to (path, width * 0.5, height);
+ clutter_path_add_line_to (path, 0, height * 0.25);
+ clutter_path_add_line_to (path, width, height * 0.25);
+ clutter_path_add_line_to (path, width * 0.5, height);
+
+ CLUTTER_ACTOR_CLASS (star_actor_parent_class)->allocate (actor, box, flags);
+}
+]]>
+
+
+
+ This clears then adds segments to the
+ ClutterPath stored with the
+ StarActor instance. The positioning and
+ lengths of the segments are relative to the size of the actor when
+ its allocation changes.
+
+ The pick and paint
+ functions now reference the ClutterPath (only the
+ pick is shown below); and
+ to turn the path into drawing operations, we implement a
+ star_actor_convert_clutter_path_node() function
+ which takes a ClutterPathNode and converts it
+ into its Cogl equivalent:
+
+
+
+type)
+ {
+ case CLUTTER_PATH_MOVE_TO:
+ knot = node->points[0];
+ cogl_path_move_to (knot.x, knot.y);
+ break;
+ case CLUTTER_PATH_LINE_TO:
+ knot = node->points[0];
+ cogl_path_line_to (knot.x, knot.y);
+ break;
+ default:
+ break;
+ }
+}
+
+static void
+star_actor_pick (ClutterActor *actor,
+ const ClutterColor *pick_color)
+{
+ if (!clutter_actor_should_pick_paint (actor))
+ return;
+
+ ClutterActorBox allocation = { 0, };
+ gfloat width, height;
+ ClutterPath *path = STAR_ACTOR (actor)->priv->path;
+
+ clutter_actor_get_allocation_box (actor, &allocation);
+ clutter_actor_box_get_size (&allocation, &width, &height);
+
+ cogl_path_new ();
+
+ cogl_set_source_color4ub (pick_color->red,
+ pick_color->green,
+ pick_color->blue,
+ pick_color->alpha);
+
+ clutter_path_foreach (path, star_actor_convert_clutter_path_node, NULL);
+
+ cogl_path_fill ();
+}
+]]>
+
+
+
+
+ The conversion function only covers
+ ClutterPathNode types encountered in this
+ actor.
+
+
+ Instead of converting to Cogl path operations, another alternative
+ would be to use the clutter_path_to_cairo_path()
+ function to write directly from the ClutterPath
+ onto a Cairo context.
+
+
+
+
+
+