mirror of
https://github.com/brl/mutter.git
synced 2024-11-23 08:30:42 -05:00
Merge remote-tracking branch 'elliot/cookbook-effects-custom-deform'
* elliot/cookbook-effects-custom-deform: docs: Add effects chapter, with introduction and first recipe
This commit is contained in:
commit
b3e4db4c73
@ -16,6 +16,7 @@ XML_FILES = \
|
||||
$(srcdir)/textures.xml \
|
||||
$(srcdir)/layouts.xml \
|
||||
$(srcdir)/script.xml \
|
||||
$(srcdir)/effects.xml \
|
||||
$(NULL)
|
||||
|
||||
XSLTOPTS = \
|
||||
@ -36,6 +37,9 @@ 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-built-in.png \
|
||||
$(srcdir)/images/effects-custom-deform.png \
|
||||
$(srcdir)/images/effects-custom-deform-back-material.png \
|
||||
$(srcdir)/images/textures-reflection.png \
|
||||
$(srcdir)/images/actors-opacity.png \
|
||||
$(srcdir)/images/actors-opacity-container-affects-opacity.png \
|
||||
@ -59,6 +63,7 @@ VIDEO_FILES = \
|
||||
$(srcdir)/videos/animations-rotating-y-centered.ogv \
|
||||
$(srcdir)/videos/animations-rotating-z-centered.ogv \
|
||||
$(srcdir)/videos/animations-rotating-container-reverses-direction.ogv \
|
||||
$(srcdir)/videos/effects-custom-deform.ogv \
|
||||
$(srcdir)/videos/textures-split-go.ogv \
|
||||
$(srcdir)/videos/events-mouse-scroll.ogv \
|
||||
$(srcdir)/videos/textures-crossfade-two-textures.ogv \
|
||||
|
@ -46,6 +46,7 @@
|
||||
<xi:include href="text.xml" />
|
||||
<xi:include href="layouts.xml" />
|
||||
<xi:include href="script.xml" />
|
||||
<xi:include href="effects.xml" />
|
||||
|
||||
<appendix id="contributing">
|
||||
<title>Contributing to this document</title>
|
||||
|
769
doc/cookbook/effects.xml
Normal file
769
doc/cookbook/effects.xml
Normal file
@ -0,0 +1,769 @@
|
||||
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
|
||||
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
|
||||
|
||||
<chapter id="effects" xmlns:xi="http://www.w3.org/2003/XInclude">
|
||||
<title>Effects</title>
|
||||
|
||||
<epigraph>
|
||||
<attribution>Roger Zelazny, from <citetitle>Prince of Chaos</citetitle>
|
||||
</attribution>
|
||||
<para>Don't wake me for the end of the world unless it has very
|
||||
good special effects</para>
|
||||
</epigraph>
|
||||
|
||||
<section id="effects-introduction">
|
||||
<title>Introduction</title>
|
||||
|
||||
<para>Effects modify an actor's appearance, such
|
||||
as how it is positioned, colored and textured.</para>
|
||||
|
||||
<para>The Clutter API for effects contains several
|
||||
abstract classes you can subclass to create your own effects.
|
||||
It also contains several built-in effects you can use to
|
||||
modify the visual appearance of actors in a variety of ways.</para>
|
||||
|
||||
<para>The recipes in this section of the cookbook cover how to create
|
||||
your own effects as well as how to apply Clutter's effects.</para>
|
||||
|
||||
<section>
|
||||
<title>Creating effects using the abstract effect classes</title>
|
||||
|
||||
<tip>
|
||||
<para>One of the original design goals of Clutter was to abstract
|
||||
the complexity of GL. However, the effects API partially circumvents
|
||||
these abstractions, to give you finer-grained access to the
|
||||
graphics pipeline. Therefore, if you want to write your own effects,
|
||||
some understanding of Cogl, OpenGL, and general graphics programming
|
||||
is essential.</para>
|
||||
</tip>
|
||||
|
||||
<para>Each abstract effect class is tailored to modifying different
|
||||
aspects of an actor, as explained below:</para>
|
||||
|
||||
<itemizedlist>
|
||||
|
||||
<listitem>
|
||||
<formalpara>
|
||||
<title><type>ClutterEffect</type></title>
|
||||
<para>If you're just using the Clutter and Cogl APIs to
|
||||
decorate an actor, this is simplest type of effect to
|
||||
implement.</para>
|
||||
</formalpara>
|
||||
|
||||
<para>Subclassing <type>ClutterEffect</type> enables you to
|
||||
"wrap" how an actor is painted, by injecting some code before
|
||||
and/or after the actor's own <function>paint()</function>
|
||||
implementation.</para>
|
||||
|
||||
<note>
|
||||
<para>This is the preferred way to modify how an actor is
|
||||
painted, short of creating your own actor subclass.</para>
|
||||
</note>
|
||||
|
||||
<para><emphasis>Subclasses of
|
||||
<type>ClutterEffect</type></emphasis>:</para>
|
||||
|
||||
<itemizedlist>
|
||||
|
||||
<listitem>
|
||||
<formalpara>
|
||||
<title><type>ClutterOffscreenEffect</type></title>
|
||||
|
||||
<para>Use this class as a basis if you need GL textures
|
||||
for your effect.</para>
|
||||
</formalpara>
|
||||
|
||||
<para>GL textures are required for effects which need
|
||||
an offscreen framebuffer. The offscreen framebuffer is
|
||||
used to store a modified rendering of an actor (e.g.
|
||||
with its colors altered or with deformed geometry).
|
||||
This buffer is then redirected to a texture in the
|
||||
stage window.</para>
|
||||
|
||||
<para>An example is <type>ClutterBlurEffect</type>,
|
||||
which uses a GLSL fragment shader to blur an
|
||||
actor's appearance in an offscreen framebuffer.</para>
|
||||
|
||||
<para><emphasis>Subclasses of
|
||||
<type>ClutterOffscreenEffect</type></emphasis>:</para>
|
||||
|
||||
<itemizedlist>
|
||||
|
||||
<listitem>
|
||||
|
||||
<formalpara>
|
||||
<title><type>ClutterDeformEffect</type></title>
|
||||
|
||||
<para>Use this base class if you want to modify
|
||||
an actor's geometry, at the level of individual
|
||||
vertices.</para>
|
||||
</formalpara>
|
||||
|
||||
<para><type>ClutterDeformEffect</type> removes the
|
||||
complexity of dealing with vertex-based deformations
|
||||
at the OpenGL level, instead enabling you to easily plug
|
||||
a deformation callback into the graphics pipeline.</para>
|
||||
|
||||
<para>If you are writing your own deform effects,
|
||||
a good example to work from is
|
||||
<type>ClutterPageTurnEffect</type>.</para>
|
||||
|
||||
<para>There is also a
|
||||
<link linkend="effects-custom-deform">recipe which
|
||||
explains how to implement a simple custom deform
|
||||
effect</link> (a page fold).</para>
|
||||
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<formalpara>
|
||||
<title><type>ClutterShaderEffect</type></title>
|
||||
|
||||
<para>Use this if you want to apply custom
|
||||
GLSL vertex or fragment shaders to your actors.</para>
|
||||
</formalpara>
|
||||
|
||||
<para>Writing <type>ClutterShaderEffects</type> gives
|
||||
you very fine-grained control over the GL pipeline.
|
||||
However, this makes them the most complex
|
||||
effects to implement.</para>
|
||||
|
||||
<tip>
|
||||
<para>If you want to write your own GLSL shaders, the
|
||||
<ulink url="http://www.opengl.org/documentation/glsl/">GLSL
|
||||
specification</ulink> is a good starting point.</para>
|
||||
</tip>
|
||||
|
||||
</listitem>
|
||||
|
||||
</itemizedlist>
|
||||
|
||||
</listitem>
|
||||
|
||||
</itemizedlist>
|
||||
|
||||
</listitem>
|
||||
|
||||
</itemizedlist>
|
||||
|
||||
</section>
|
||||
|
||||
<section id="effects-introduction-using-the-built-in-effects">
|
||||
<title>Using the built-in effects</title>
|
||||
|
||||
<para>Clutter comes with a number of built-in effects
|
||||
which can easily be applied to your actors. This section
|
||||
explains how to do this.</para>
|
||||
|
||||
<para>First, create an actor. For this
|
||||
example, we use a texture loaded with an image:</para>
|
||||
|
||||
<informalexample>
|
||||
<programlisting>
|
||||
/* filename could be set from command line or constant */
|
||||
gchar *filename;
|
||||
|
||||
/* create a texture */
|
||||
ClutterActor *texture = clutter_texture_new ();
|
||||
|
||||
/* ...set texture size, keep aspect ratio etc... */
|
||||
|
||||
/* NB ignoring missing file errors here for brevity */
|
||||
clutter_texture_set_from_file (CLUTTER_TEXTURE (texture),
|
||||
filename,
|
||||
NULL);
|
||||
|
||||
/* ...add texture to the stage... */
|
||||
</programlisting>
|
||||
</informalexample>
|
||||
|
||||
<para>Next, create an instance of an effect; here, we're
|
||||
creating a <type>ClutterColorizeEffect</type> with a pink tint:</para>
|
||||
|
||||
<informalexample>
|
||||
<programlisting>
|
||||
ClutterColor *pink = clutter_color_new (230, 187, 210, 255);
|
||||
ClutterEffect *effect = clutter_colorize_effect_new (pink);
|
||||
</programlisting>
|
||||
</informalexample>
|
||||
|
||||
<para>Finally, apply the effect to the actor:</para>
|
||||
|
||||
<informalexample>
|
||||
<programlisting>
|
||||
clutter_actor_add_effect (texture, effect);
|
||||
</programlisting>
|
||||
</informalexample>
|
||||
|
||||
<para>The result in this case is an image colorized with
|
||||
a pink tint, like this:</para>
|
||||
|
||||
<screenshot>
|
||||
<mediaobject>
|
||||
<imageobject>
|
||||
<imagedata format="PNG"
|
||||
fileref="images/effects-built-in.png" />
|
||||
</imageobject>
|
||||
<alt>
|
||||
<para>Applying a <type>ClutterColorizeEffect</type>
|
||||
to a texture loaded with an image (drawing by
|
||||
Madeleine Smith)</para>
|
||||
</alt>
|
||||
</mediaobject>
|
||||
</screenshot>
|
||||
|
||||
<para>The same set of steps applies for any of the built-in
|
||||
Clutter effects. Your own custom effects classes should also
|
||||
behave in a similar way: constructors should return
|
||||
<type>ClutterEffect</type> instances so your effect can
|
||||
be added to an actor through the standard API.</para>
|
||||
|
||||
<para>One further thing worth mentioning is that because an
|
||||
effect is a GObject, any properties you expose for your effect
|
||||
can be animated via implicit animations,
|
||||
<type>ClutterAnimator</type> or <type>ClutterState</type>. For
|
||||
example, the <type>ClutterPageTurnEffect</type> can be animated
|
||||
by manipulating its <varname>period</varname> property. An example
|
||||
of how to do this for your own effect is given in the
|
||||
<link linkend="effects-custom-deform">custom deform effect
|
||||
recipe</link>.</para>
|
||||
|
||||
<para>The full code for the <type>ClutterColorizeEffect</type>
|
||||
example is below.</para>
|
||||
|
||||
<example id="effects-introduction-example-1">
|
||||
<title>Applying a <type>ClutterColorizeEffect</type> to
|
||||
a texture loaded with an image</title>
|
||||
<programlisting>
|
||||
<xi:include href="examples/effects-built-in.c" parse="text">
|
||||
<xi:fallback>a code sample should be here... but isn't</xi:fallback>
|
||||
</xi:include>
|
||||
</programlisting>
|
||||
</example>
|
||||
|
||||
</section>
|
||||
|
||||
</section>
|
||||
|
||||
<section id="effects-custom-deform">
|
||||
<title>Creating and animating a custom <type>ClutterDeformEffect</type></title>
|
||||
|
||||
<section>
|
||||
<title>Problem</title>
|
||||
|
||||
<para>You want to deform an actor's geometry: for example,
|
||||
to make it appear stretched, twisted or folded.</para>
|
||||
|
||||
<para>This recipe demonstrates how to do this with a simple page
|
||||
fold effect, which folds one half of the actor over its other half.</para>
|
||||
</section>
|
||||
|
||||
<section id="effects-custom-deform-solution">
|
||||
<title>Solution</title>
|
||||
|
||||
<para>Subclass <type>ClutterDeformEffect</type> and
|
||||
implement a <function>deform_vertex()</function> function
|
||||
to modify the actor's vertices.</para>
|
||||
|
||||
<para>The signature for <function>deform_vertex()</function>
|
||||
is:</para>
|
||||
|
||||
<informalexample>
|
||||
<programlisting>
|
||||
void
|
||||
deform_vertex (ClutterDeformEffect *effect,
|
||||
gfloat width,
|
||||
gfloat height,
|
||||
CoglTextureVertex *vertex);
|
||||
</programlisting>
|
||||
</informalexample>
|
||||
|
||||
<para>The <varname>width</varname> and <varname>height</varname>
|
||||
are the width and height of the target material, stored in
|
||||
the offscreen buffer. Usually the target material's size will
|
||||
match the actor's transformed size; however, if the effect
|
||||
implements <function>create_texture()</function>, the target
|
||||
material's size may differ from the actor's transformed size.</para>
|
||||
|
||||
<para>The <varname>vertex</varname> contains the position
|
||||
and color of a vertex, to be deformed by your effect.
|
||||
Your <function>deform_vertex()</function>
|
||||
function should modify the member variables of this
|
||||
<type>CoglTextureVertex</type> in place. Usually, this will
|
||||
mean modifying the <varname>x</varname>, <varname>y</varname>
|
||||
and <varname>y</varname> member variables of the vertex,
|
||||
which describe its position in 3D space.</para>
|
||||
|
||||
<para>The example function below, taken from
|
||||
<link linkend="effects-custom-deform-example-2">the
|
||||
full example</link>, applies a transformation to vertices falling
|
||||
in the "right-hand" half of the actor (i.e. vertices with an
|
||||
<varname>x</varname> value greater than or equal to half the
|
||||
width of the actor).</para>
|
||||
|
||||
<informalexample>
|
||||
<programlisting>
|
||||
static void
|
||||
cb_page_fold_effect_deform_vertex (ClutterDeformEffect *effect,
|
||||
gfloat width,
|
||||
gfloat height,
|
||||
CoglTextureVertex *vertex)
|
||||
{
|
||||
CbPageFoldEffectPrivate *priv = CB_PAGE_FOLD_EFFECT (effect)->priv;
|
||||
|
||||
/* the rotation angle is modified by the percentage progress of the fold,
|
||||
* as represented by the period variable
|
||||
*/
|
||||
gfloat radians = (priv->angle * priv->period) / (180.0f / G_PI);
|
||||
|
||||
/* rotate from the center of the actor on the y axis */
|
||||
gfloat adjusted_x = vertex->x - (width / 2);
|
||||
|
||||
/* only rotate vertices to the right of the middle of the actor */
|
||||
if (adjusted_x >= 0.0)
|
||||
{
|
||||
vertex->x = (vertex->z * sin (radians))
|
||||
+ (adjusted_x * cos (radians))
|
||||
+ width / 2;
|
||||
|
||||
/* NB add 1 to z to prevent "z fighting"; otherwise, when fully-folded
|
||||
* the image has "stripes" where vertices from the folded part
|
||||
* of the actor interfere with vertices from the unfolded part
|
||||
*/
|
||||
vertex->z = (vertex->z * cos (radians))
|
||||
+ (adjusted_x * sin (radians))
|
||||
+ 1;
|
||||
}
|
||||
|
||||
/* adjust depth of all vertices so they fit inside the actor while folding;
|
||||
* this has the effect of making the image smaller within the texture,
|
||||
* but does produce a cleaner fold animation
|
||||
*/
|
||||
vertex->z -= width / 2;
|
||||
}
|
||||
</programlisting>
|
||||
</informalexample>
|
||||
|
||||
<para>Note that this effect has two properties set in its
|
||||
constructor or through setters:</para>
|
||||
|
||||
<orderedlist>
|
||||
<listitem>
|
||||
<para><varname>angle</varname>, representing the angle of
|
||||
the full fold; for the actor to fully fold in half, this
|
||||
would be set to 180.0</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para><varname>period</varname>, representing the percentage
|
||||
of the fold to apply</para>
|
||||
</listitem>
|
||||
</orderedlist>
|
||||
|
||||
<para>As well as rotating the vertex, the
|
||||
<function>deform_vertex()</function> function also shifts
|
||||
the <varname>z</varname> coordinate "up" by 1
|
||||
(towards the viewpoint) for vertices on the right-hand side of the
|
||||
actor. This is so that the "folded over" vertices
|
||||
are above vertices on the left-hand side. Without this small
|
||||
shift, the vertices interfere with each other, which can cause striping
|
||||
artefacts.</para>
|
||||
|
||||
<para><emphasis>All</emphasis> vertices are also shifted "down",
|
||||
so that the the folding part of the actor remains within the texture.
|
||||
Otherwise the part which is folding may be clipped to the allocation of
|
||||
the actor.</para>
|
||||
|
||||
<para>This effect can now be applied to an actor, using the
|
||||
approach
|
||||
<link linkend="effects-introduction-using-the-built-in-effects">outlined
|
||||
in the introduction</link>. The result looks like this when
|
||||
<varname>period</varname> is set to 0.25 and <varname>angle</varname>
|
||||
to 180.0 (i.e. the page is folded by 45 degrees):</para>
|
||||
|
||||
<screenshot>
|
||||
<mediaobject>
|
||||
<imageobject>
|
||||
<imagedata format="PNG"
|
||||
fileref="images/effects-custom-deform.png" />
|
||||
</imageobject>
|
||||
<alt>
|
||||
<para>Applying a custom <type>ClutterDeformEffect</type>
|
||||
to a texture loaded with an image</para>
|
||||
</alt>
|
||||
</mediaobject>
|
||||
</screenshot>
|
||||
|
||||
<para>Because the effect is a GObject which exposes its
|
||||
properties, it can easily be animated, as described in
|
||||
<link linkend="effects-custom-deform-discussion-animating">the
|
||||
discussion section</link>.</para>
|
||||
|
||||
</section>
|
||||
|
||||
<section id="effects-custom-deform-discussion">
|
||||
<title>Discussion</title>
|
||||
|
||||
<para>A deform effect processes an actor as follows:</para>
|
||||
|
||||
<itemizedlist>
|
||||
|
||||
<listitem>
|
||||
<para>The actor is divided into a series of
|
||||
triangular tiles. The number of
|
||||
horizontal and vertical tiles is configurable;
|
||||
more tiles implies more vertices. See
|
||||
<link linkend="effects-custom-deform-discussion-tiles">this
|
||||
section</link> for more details about tiles.</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>The position of each vertex of each
|
||||
tile is then modified (or not) by the
|
||||
<function>deform_vertex()</function> function. In this
|
||||
function, you can change the vertex's position
|
||||
(<varname>x</varname>, <varname>y</varname>,
|
||||
<varname>z</varname> coordinates). You can also
|
||||
modify the color at the vertex if desired.</para>
|
||||
|
||||
<para>The resulting deformed vertices are stored
|
||||
in an offscreen buffer.</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>Once the deformation has been applied to
|
||||
all vertices, the content of the offscreen buffer
|
||||
is painted at the onscreen position of the actor.</para>
|
||||
</listitem>
|
||||
|
||||
</itemizedlist>
|
||||
|
||||
<para>You may find it useful to visualise this process by imagining
|
||||
your actor's surface as a net, composed of triangles. (Something
|
||||
like a fishing net, not a mathematical one.) At each corner of
|
||||
each triangle is a marble; and between each pair of corners
|
||||
is an infinitely flexible length of elastic. Moving a marble
|
||||
doesn't change the position of its neighbours; it just stretches
|
||||
or relaxes the elastic.</para>
|
||||
|
||||
<para>In this analogy, the marbles are the vertices; and the
|
||||
surfaces between the marbles, bordered by triangles of
|
||||
elastic, are the tiles. More triangles (tiles) means more
|
||||
marbles (vertices).</para>
|
||||
|
||||
<para>When you create a <type>ClutterDeformEffect</type>,
|
||||
think of it as specifying movements of marbles in the net.
|
||||
Changing the position of a vertex corresponds to moving a marble
|
||||
up/down (-/+ <varname>y</varname> position), left/right
|
||||
(-/+ <varname>x</varname> position) or away/towards
|
||||
you (-/+ <varname>z</varname> position) (ignoring color for the
|
||||
moment).</para>
|
||||
|
||||
<para>Now imagine that you are asked to fold the whole net of
|
||||
marbles; but you can't just grab the edge of the net and pull
|
||||
it over: you can only move one marble at a time. However, once moved,
|
||||
each marble magically stays where you put it in 3D space.</para>
|
||||
|
||||
<para>To do this, you could project where each marble would be if
|
||||
you could fold the whole sheet in one go; then move the
|
||||
marbles one by one to their projected positions. Even though
|
||||
you'd be moving the marbles one at a time, it would eventually
|
||||
look as though you'd folded the whole net with a single movement.</para>
|
||||
|
||||
<para>When you write a <type>ClutterDeformEffect</type>, you have
|
||||
to accomplish a similar feat: change the shape of an actor
|
||||
by individually modifying the positions of points on its surface. In
|
||||
most cases, your <function>deform_vertex()</function> implementation
|
||||
can take advantage of an existing geometric transformation
|
||||
method to achieve this. (For example, the page fold in this recipe
|
||||
is based on equations from p.412 of <citetitle pubwork="book">Computer
|
||||
Graphics (C Version), 2nd Edition</citetitle> by Hearn and
|
||||
Baker, 1996.)</para>
|
||||
|
||||
<section>
|
||||
<title>Customising the back material</title>
|
||||
|
||||
<para>When you set up a deform effect, you
|
||||
can optionally specify a material to use for the "back" of
|
||||
any actor it is applied to.</para>
|
||||
|
||||
<para>If you think of an actor as a sheet of paper with a
|
||||
picture on it, specifying a back is similar to turning the
|
||||
sheet of paper over (rotating it around the
|
||||
<varname>y</varname> axis) and drawing another picture on
|
||||
the other side. If you then folded or twisted the paper,
|
||||
you would be able to see parts of the pictures on both the
|
||||
front and back of the paper.</para>
|
||||
|
||||
<para>Similarly, during deformation of an actor, if any
|
||||
vertices of the actor are deformed such that the actor's surface
|
||||
is folded or twisted over itself, parts of its back
|
||||
become visible. If you set a back material, you will see parts
|
||||
of that where the surface is folded over. If you don't set a back
|
||||
material, you will instead see mirror images of parts of the actor's
|
||||
front: as if the actor was flexible stained glass, rather than paper.
|
||||
You can see this if you watch the animation in
|
||||
<link linkend="effects-custom-deform-discussion-animating">this
|
||||
section</link>.</para>
|
||||
|
||||
<para>The back material should be an instance of
|
||||
<type>CoglMaterial</type>. You can either create this via
|
||||
the Cogl API directly; or indirectly through the Clutter API
|
||||
(for example, by getting the material from a
|
||||
<type>ClutterTexture</type>). The code below gives an example
|
||||
of how to do the latter:</para>
|
||||
|
||||
<informalexample>
|
||||
<programlisting>
|
||||
<![CDATA[
|
||||
/* create a texture */
|
||||
ClutterActor *back = clutter_texture_new ();
|
||||
clutter_texture_set_keep_aspect_ratio (CLUTTER_TEXTURE (back), TRUE);
|
||||
clutter_actor_set_width (back, 400);
|
||||
|
||||
/* load image into texture (ignoring errors for brevity) */
|
||||
clutter_texture_set_from_file (CLUTTER_TEXTURE (back),
|
||||
back_image_file,
|
||||
NULL);
|
||||
|
||||
/* get a handle to the texture's Cogl material */
|
||||
CoglHandle material = clutter_texture_get_cogl_material (CLUTTER_TEXTURE (back));
|
||||
|
||||
/* cast the effect to ClutterDeformEffect and set its back material
|
||||
* to the handle
|
||||
*/
|
||||
clutter_deform_effect_set_back_material (CLUTTER_DEFORM_EFFECT (effect),
|
||||
material);
|
||||
]]>
|
||||
</programlisting>
|
||||
</informalexample>
|
||||
|
||||
<para>See the <type>ClutterDeformEffect</type> API reference
|
||||
for more details about back materials.</para>
|
||||
|
||||
<para>Here's a screenshot of the
|
||||
<link linkend="effects-custom-deform-example-3">example</link>
|
||||
with the addition of a back material, folded at an angle
|
||||
of 60 degrees:</para>
|
||||
|
||||
<screenshot>
|
||||
<mediaobject>
|
||||
<imageobject>
|
||||
<imagedata format="PNG"
|
||||
fileref="images/effects-custom-deform-back-material.png" />
|
||||
</imageobject>
|
||||
<alt>
|
||||
<para>Applying a custom <type>ClutterDeformEffect</type>
|
||||
to a texture loaded with an image</para>
|
||||
</alt>
|
||||
</mediaobject>
|
||||
</screenshot>
|
||||
|
||||
</section>
|
||||
|
||||
<section id="effects-custom-deform-discussion-animating">
|
||||
<title>Animating a custom deform effect</title>
|
||||
|
||||
<para>Clutter's animation API can animate any GObject which
|
||||
exposes its properties. In the case of the page fold effect,
|
||||
we can expose the <varname>period</varname> property using
|
||||
standard GObject property installation:</para>
|
||||
|
||||
<informalexample>
|
||||
<programlisting>
|
||||
/* GObject class init */
|
||||
static void
|
||||
cb_page_fold_effect_class_init (CbPageFoldEffectClass *klass)
|
||||
{
|
||||
GParamSpec *pspec;
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
/* ...other class setup code... */
|
||||
|
||||
/* expose the period as a GObject property */
|
||||
pspec = g_param_spec_double ("period",
|
||||
"Period",
|
||||
"The period of the page fold",
|
||||
0.0, 1.0,
|
||||
0.0,
|
||||
G_PARAM_READWRITE);
|
||||
obj_props[PROP_PERIOD] = pspec;
|
||||
g_object_class_install_property (gobject_class, PROP_PERIOD, pspec);
|
||||
|
||||
/* ...install other properties... */
|
||||
}
|
||||
</programlisting>
|
||||
</informalexample>
|
||||
|
||||
<para>We also add a <function>get_property()</function>
|
||||
implementation, as well as a setter (see
|
||||
<link linkend="effects-custom-deform-example-2">the full
|
||||
GObject implementation</link> for details).</para>
|
||||
|
||||
<para>Then set up an animation for the property; in this case,
|
||||
using a <type>ClutterState</type>:</para>
|
||||
|
||||
<informalexample>
|
||||
<programlisting>
|
||||
ClutterEffect *effect = cb_page_fold_effect_new (180.0, 0.0);
|
||||
|
||||
ClutterState *transitions = clutter_state_new ();
|
||||
clutter_state_set_duration (transitions, NULL, NULL, 500);
|
||||
|
||||
clutter_state_set (transitions, NULL, "unfolded",
|
||||
effect, "period", CLUTTER_LINEAR, 0.0,
|
||||
NULL);
|
||||
|
||||
clutter_state_set (transitions, NULL, "folded",
|
||||
effect, "period", CLUTTER_LINEAR, 1.0,
|
||||
NULL);
|
||||
</programlisting>
|
||||
</informalexample>
|
||||
|
||||
<para>To start the animation, warp the <type>ClutterState</type>
|
||||
into its <emphasis>"unfolded"</emphasis> state, then set it to
|
||||
<emphasis>"folded"</emphasis>:</para>
|
||||
|
||||
<informalexample>
|
||||
<programlisting>
|
||||
/* this changes state instantaneously */
|
||||
clutter_state_warp_to_state (transitions, "unfolded");
|
||||
|
||||
/* this starts an animation to the state */
|
||||
clutter_state_set_state (transitions, "folded");
|
||||
</programlisting>
|
||||
</informalexample>
|
||||
|
||||
<para>Note that the
|
||||
<link linkend="effects-custom-deform-example-3">full code
|
||||
sample</link> is slightly more complex, as it triggers state
|
||||
changes when a mouse button is pressed on the texture. There is
|
||||
also a third "partially folded" state (used to create
|
||||
the screenshot for the
|
||||
<link linkend="effects-custom-deform-solution">previous
|
||||
section</link>).</para>
|
||||
|
||||
<para>Here's what the resulting animation looks like:</para>
|
||||
|
||||
<inlinemediaobject>
|
||||
<videoobject>
|
||||
<videodata fileref="videos/effects-custom-deform.ogv"/>
|
||||
</videoobject>
|
||||
<alt>
|
||||
<para>Video showing animation of a custom deform effect
|
||||
on a texture</para>
|
||||
</alt>
|
||||
</inlinemediaobject>
|
||||
|
||||
</section>
|
||||
|
||||
<section id="effects-custom-deform-discussion-tiles">
|
||||
<title>Tiles</title>
|
||||
|
||||
<para>A <type>ClutterDeformEffect</type> divides the actor
|
||||
being deformed into a number of tiles: the larger the number
|
||||
of tiles, the larger the number of vertices to be manipulated
|
||||
by the effect. Increasing the number of tiles increases the number of
|
||||
vertex computations required, which can slow down animations;
|
||||
at the same time, finer-grained tiles can make an effect appear
|
||||
smoother, particularly when animated.</para>
|
||||
|
||||
<para>Most of the time, the default number
|
||||
of tiles in the <varname>x</varname> and <varname>y</varname>
|
||||
axes should suffice. You can get the current number of
|
||||
tiles associated with an effect with:</para>
|
||||
|
||||
<informalexample>
|
||||
<programlisting>
|
||||
<![CDATA[
|
||||
guint x_tiles;
|
||||
guint y_tiles;
|
||||
|
||||
/* effect must be a subclass of ClutterDeformEffect */
|
||||
clutter_deform_effect_get_n_tiles (CLUTTER_DEFORM_EFFECT (effect),
|
||||
&x_tiles,
|
||||
&y_tiles);
|
||||
]]>
|
||||
</programlisting>
|
||||
</informalexample>
|
||||
|
||||
<para>However, if an effect produces jerky or fragmented output,
|
||||
you want to tweak the number of tiles. Use the
|
||||
<function>clutter_deform_effect_set_n_tiles()</function> function
|
||||
to do this:</para>
|
||||
|
||||
<informalexample>
|
||||
<programlisting>
|
||||
/* 64 tiles in both axes */
|
||||
guint x_tiles = 64;
|
||||
guint y_tiles = 64;
|
||||
|
||||
clutter_deform_effect_set_n_tiles (CLUTTER_DEFORM_EFFECT (effect),
|
||||
x_tiles,
|
||||
y_tiles);
|
||||
</programlisting>
|
||||
</informalexample>
|
||||
|
||||
</section>
|
||||
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<title>Full example</title>
|
||||
|
||||
<para>This example consists of three files:</para>
|
||||
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para><link linkend="effects-custom-deform-example-1">A header
|
||||
file</link> for the <type>CbPageFoldEffect</type> GObject.</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para><link linkend="effects-custom-deform-example-2">The
|
||||
code file</link> implementing <type>CbPageFoldEffect</type>.</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para><link linkend="effects-custom-deform-example-3">A short
|
||||
sample application</link> which applies a <type>CbPageFoldEffect</type>
|
||||
instance to an actor and animates the fold when the actor is
|
||||
clicked.</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
|
||||
<para>As Clutter effect subclasses are written using GObject,
|
||||
you might find <link linkend="actors-composite">this recipe</link>
|
||||
(which goes into GObject in more detail) a useful introduction.</para>
|
||||
|
||||
<example id="effects-custom-deform-example-1">
|
||||
<title><filename>cb-page-fold-effect.h</filename> (header file)</title>
|
||||
<programlisting>
|
||||
<xi:include href="examples/cb-page-fold-effect.h" parse="text">
|
||||
<xi:fallback>a code sample should be here... but isn't</xi:fallback>
|
||||
</xi:include>
|
||||
</programlisting>
|
||||
</example>
|
||||
|
||||
<example id="effects-custom-deform-example-2">
|
||||
<title><filename>cb-page-fold-effect.c</filename> (code file)</title>
|
||||
<programlisting>
|
||||
<xi:include href="examples/cb-page-fold-effect.c" parse="text">
|
||||
<xi:fallback>a code sample should be here... but isn't</xi:fallback>
|
||||
</xi:include>
|
||||
</programlisting>
|
||||
</example>
|
||||
|
||||
<example id="effects-custom-deform-example-3">
|
||||
<title>Application which uses <type>CbPageFoldEffect</type>
|
||||
to do animated folding of a <type>ClutterTexture</type></title>
|
||||
<programlisting>
|
||||
<xi:include href="examples/effects-custom-deform.c" parse="text">
|
||||
<xi:fallback>a code sample should be here... but isn't</xi:fallback>
|
||||
</xi:include>
|
||||
</programlisting>
|
||||
</example>
|
||||
|
||||
</section>
|
||||
|
||||
</section>
|
||||
|
||||
</chapter>
|
@ -18,6 +18,8 @@ noinst_PROGRAMS = \
|
||||
animations-rotating \
|
||||
animations-scaling \
|
||||
animations-scaling-zoom \
|
||||
effects-built-in \
|
||||
effects-custom-deform \
|
||||
text-shadow \
|
||||
textures-reflection \
|
||||
textures-split-go \
|
||||
@ -81,6 +83,8 @@ animations_reuse_SOURCES = animations-reuse.c
|
||||
animations_rotating_SOURCES = animations-rotating.c
|
||||
animations_scaling_SOURCES = animations-scaling.c
|
||||
animations_scaling_zoom_SOURCES = animations-scaling-zoom.c
|
||||
effects_built_in_SOURCES = effects-built-in.c
|
||||
effects_custom_deform_SOURCES = cb-page-fold-effect.c cb-page-fold-effect.h effects-custom-deform.c
|
||||
text_shadow_SOURCES = text-shadow.c
|
||||
textures_reflection_SOURCES = textures-reflection.c
|
||||
textures_split_go_SOURCES = textures-split-go.c
|
||||
|
250
doc/cookbook/examples/cb-page-fold-effect.c
Normal file
250
doc/cookbook/examples/cb-page-fold-effect.c
Normal file
@ -0,0 +1,250 @@
|
||||
#include <math.h>
|
||||
#include "cb-page-fold-effect.h"
|
||||
|
||||
G_DEFINE_TYPE (CbPageFoldEffect, cb_page_fold_effect, CLUTTER_TYPE_DEFORM_EFFECT);
|
||||
|
||||
#define CB_PAGE_FOLD_EFFECT_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \
|
||||
CB_TYPE_PAGE_FOLD_EFFECT, \
|
||||
CbPageFoldEffectPrivate))
|
||||
|
||||
struct _CbPageFoldEffectPrivate
|
||||
{
|
||||
gdouble angle;
|
||||
gdouble period;
|
||||
};
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
|
||||
PROP_PERIOD,
|
||||
PROP_ANGLE,
|
||||
|
||||
PROP_LAST
|
||||
};
|
||||
|
||||
static GParamSpec *obj_props[PROP_LAST];
|
||||
|
||||
/* ClutterDeformEffect implementation */
|
||||
static void
|
||||
cb_page_fold_effect_deform_vertex (ClutterDeformEffect *effect,
|
||||
gfloat width,
|
||||
gfloat height,
|
||||
CoglTextureVertex *vertex)
|
||||
{
|
||||
CbPageFoldEffectPrivate *priv = CB_PAGE_FOLD_EFFECT (effect)->priv;
|
||||
|
||||
gfloat radians = (priv->angle * priv->period) / (180.0f / G_PI);
|
||||
|
||||
/* rotate from the center of the actor on the y axis */
|
||||
gfloat adjusted_x = vertex->x - (width / 2);
|
||||
|
||||
/* only rotate vertices to the right of the middle of the actor */
|
||||
if (adjusted_x >= 0.0)
|
||||
{
|
||||
vertex->x = (vertex->z * sin (radians))
|
||||
+ (adjusted_x * cos (radians))
|
||||
+ width / 2;
|
||||
|
||||
/* NB add 1 to z to prevent "z fighting"; otherwise, when fully-folded
|
||||
* the image has "stripes" where vertices from the folded part
|
||||
* of the actor interfere with vertices from the unfolded part
|
||||
*/
|
||||
vertex->z = (vertex->z * cos (radians))
|
||||
+ (adjusted_x * sin (radians))
|
||||
+ 1;
|
||||
}
|
||||
|
||||
/* adjust depth of all vertices so they fit inside the actor while folding;
|
||||
* this has the effect of making the image smaller within the texture,
|
||||
* but does produce a cleaner fold animation
|
||||
*/
|
||||
vertex->z -= width / 2;
|
||||
}
|
||||
|
||||
/* GObject implementation */
|
||||
static void
|
||||
cb_page_fold_effect_set_property (GObject *gobject,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
CbPageFoldEffect *effect = CB_PAGE_FOLD_EFFECT (gobject);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_PERIOD:
|
||||
cb_page_fold_effect_set_period (effect, g_value_get_double (value));
|
||||
break;
|
||||
|
||||
case PROP_ANGLE:
|
||||
cb_page_fold_effect_set_angle (effect, g_value_get_double (value));
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
cb_page_fold_effect_get_property (GObject *gobject,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
CbPageFoldEffectPrivate *priv = CB_PAGE_FOLD_EFFECT (gobject)->priv;
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_PERIOD:
|
||||
g_value_set_double (value, priv->period);
|
||||
break;
|
||||
|
||||
case PROP_ANGLE:
|
||||
g_value_set_double (value, priv->angle);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* GObject class and instance init */
|
||||
static void
|
||||
cb_page_fold_effect_class_init (CbPageFoldEffectClass *klass)
|
||||
{
|
||||
GParamSpec *pspec;
|
||||
ClutterDeformEffectClass *effect_class = CLUTTER_DEFORM_EFFECT_CLASS (klass);
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
effect_class->deform_vertex = cb_page_fold_effect_deform_vertex;
|
||||
|
||||
gobject_class->set_property = cb_page_fold_effect_set_property;
|
||||
gobject_class->get_property = cb_page_fold_effect_get_property;
|
||||
|
||||
g_type_class_add_private (klass, sizeof (CbPageFoldEffectPrivate));
|
||||
|
||||
/**
|
||||
* CbPageFoldEffect:period:
|
||||
*
|
||||
* The period of the page fold, between 0.0 (no fold) and
|
||||
* 1.0 (fully folded)
|
||||
*/
|
||||
pspec = g_param_spec_double ("period",
|
||||
"Period",
|
||||
"The period of the page fold",
|
||||
0.0, 1.0,
|
||||
0.0,
|
||||
G_PARAM_READWRITE);
|
||||
obj_props[PROP_PERIOD] = pspec;
|
||||
g_object_class_install_property (gobject_class, PROP_PERIOD, pspec);
|
||||
|
||||
/**
|
||||
* CbPageFoldEffect:angle:
|
||||
*
|
||||
* The angle of the page fold, in degrees, between 0.0 and 180.0
|
||||
*/
|
||||
pspec = g_param_spec_double ("angle",
|
||||
"Angle",
|
||||
"The angle of the page fold, in degrees",
|
||||
0.0, 180.0,
|
||||
0.0,
|
||||
G_PARAM_READWRITE);
|
||||
obj_props[PROP_ANGLE] = pspec;
|
||||
g_object_class_install_property (gobject_class, PROP_ANGLE, pspec);
|
||||
}
|
||||
|
||||
static void
|
||||
cb_page_fold_effect_init (CbPageFoldEffect *self)
|
||||
{
|
||||
CbPageFoldEffectPrivate *priv;
|
||||
|
||||
priv = self->priv = CB_PAGE_FOLD_EFFECT_GET_PRIVATE (self);
|
||||
|
||||
priv->period = 0.0;
|
||||
priv->angle = 0.0;
|
||||
}
|
||||
|
||||
/* public API */
|
||||
ClutterEffect *
|
||||
cb_page_fold_effect_new (gdouble angle,
|
||||
gdouble period)
|
||||
{
|
||||
return g_object_new (CB_TYPE_PAGE_FOLD_EFFECT,
|
||||
"angle", angle,
|
||||
"period", period,
|
||||
NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* cb_page_fold_effect_set_period:
|
||||
* @effect: a #CbPageFoldEffect
|
||||
* @period: the period of the page fold, between 0.0 and 1.0
|
||||
*
|
||||
* Sets the period of the page fold, between 0.0 (no fold)
|
||||
* and 1.0 (fully folded)
|
||||
*/
|
||||
void
|
||||
cb_page_fold_effect_set_period (CbPageFoldEffect *effect,
|
||||
gdouble period)
|
||||
{
|
||||
g_return_if_fail (CB_IS_PAGE_FOLD_EFFECT (effect));
|
||||
g_return_if_fail (period >= 0.0 && period <= 1.0);
|
||||
|
||||
effect->priv->period = period;
|
||||
|
||||
clutter_deform_effect_invalidate (CLUTTER_DEFORM_EFFECT (effect));
|
||||
}
|
||||
|
||||
/**
|
||||
* cb_page_fold_effect_get_period:
|
||||
* @effect: a #CbPageFoldEffect
|
||||
*
|
||||
* Retrieves the value set using cb_page_fold_effect_get_period()
|
||||
*
|
||||
* Return value: the period of the page fold
|
||||
*/
|
||||
gdouble
|
||||
cb_page_fold_effect_get_period (CbPageFoldEffect *effect)
|
||||
{
|
||||
g_return_val_if_fail (CB_IS_PAGE_FOLD_EFFECT (effect), 0.0);
|
||||
|
||||
return effect->priv->period;
|
||||
}
|
||||
|
||||
/**
|
||||
* cb_page_fold_effect_set_angle:
|
||||
* @effect: #CbPageFoldEffect
|
||||
* @angle: the angle of the page fold, in degrees
|
||||
*
|
||||
* Sets the angle of the page fold, in degrees; must be a value between
|
||||
* 0.0 and 180.0
|
||||
*/
|
||||
void
|
||||
cb_page_fold_effect_set_angle (CbPageFoldEffect *effect,
|
||||
gdouble angle)
|
||||
{
|
||||
g_return_if_fail (CB_IS_PAGE_FOLD_EFFECT (effect));
|
||||
g_return_if_fail (angle >= 0.0 && angle <= 180.0);
|
||||
|
||||
effect->priv->angle = angle;
|
||||
|
||||
clutter_deform_effect_invalidate (CLUTTER_DEFORM_EFFECT (effect));
|
||||
}
|
||||
|
||||
/**
|
||||
* cb_page_fold_effect_get_angle:
|
||||
* @effect: a #CbPageFoldEffect:
|
||||
*
|
||||
* Retrieves the angle of the page fold, in degrees
|
||||
*
|
||||
* Return value: the angle of the page fold
|
||||
*/
|
||||
gdouble
|
||||
cb_page_fold_effect_get_angle (CbPageFoldEffect *effect)
|
||||
{
|
||||
g_return_val_if_fail (CB_IS_PAGE_FOLD_EFFECT (effect), 0.0);
|
||||
|
||||
return effect->priv->angle;
|
||||
}
|
49
doc/cookbook/examples/cb-page-fold-effect.h
Normal file
49
doc/cookbook/examples/cb-page-fold-effect.h
Normal file
@ -0,0 +1,49 @@
|
||||
#ifndef __CB_PAGE_FOLD_EFFECT_H__
|
||||
#define __CB_PAGE_FOLD_EFFECT_H__
|
||||
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
GType cb_page_fold_effect_get_type (void);
|
||||
|
||||
#define CB_TYPE_PAGE_FOLD_EFFECT (cb_page_fold_effect_get_type ())
|
||||
#define CB_PAGE_FOLD_EFFECT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
|
||||
CB_TYPE_PAGE_FOLD_EFFECT, \
|
||||
CbPageFoldEffect))
|
||||
#define CB_IS_PAGE_FOLD_EFFECT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
|
||||
CB_TYPE_PAGE_FOLD_EFFECT))
|
||||
#define CB_PAGE_FOLD_EFFECT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), \
|
||||
CB_TYPE_PAGE_FOLD_EFFECT, \
|
||||
CbPageFoldEffectClass))
|
||||
#define CB_IS_PAGE_FOLD_EFFECT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), \
|
||||
CB_TYPE_PAGE_FOLD_EFFECT))
|
||||
#define CB_PAGE_FOLD_EFFECT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), \
|
||||
CB_TYPE_PAGE_FOLD_EFFECT, \
|
||||
CbPageFoldEffectClass))
|
||||
|
||||
typedef struct _CbPageFoldEffectPrivate CbPageFoldEffectPrivate;
|
||||
typedef struct _CbPageFoldEffect CbPageFoldEffect;
|
||||
typedef struct _CbPageFoldEffectClass CbPageFoldEffectClass;
|
||||
|
||||
/* object */
|
||||
struct _CbPageFoldEffect
|
||||
{
|
||||
ClutterDeformEffect parent_instance;
|
||||
CbPageFoldEffectPrivate *priv;
|
||||
};
|
||||
|
||||
/* class */
|
||||
struct _CbPageFoldEffectClass
|
||||
{
|
||||
ClutterDeformEffectClass parent_class;
|
||||
};
|
||||
|
||||
ClutterEffect *cb_page_fold_effect_new (gdouble angle,
|
||||
gdouble period);
|
||||
void cb_page_fold_effect_set_angle (CbPageFoldEffect *effect,
|
||||
gdouble angle);
|
||||
void cb_page_fold_effect_set_period (CbPageFoldEffect *effect,
|
||||
gdouble period);
|
||||
gdouble cb_page_fold_effect_get_period (CbPageFoldEffect *effect);
|
||||
gdouble cb_page_fold_effect_get_angle (CbPageFoldEffect *effect);
|
||||
|
||||
#endif /* __CB_PAGE_FOLD_EFFECT_H__ */
|
58
doc/cookbook/examples/effects-built-in.c
Normal file
58
doc/cookbook/examples/effects-built-in.c
Normal file
@ -0,0 +1,58 @@
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
int
|
||||
main (int argc,
|
||||
char *argv[])
|
||||
{
|
||||
ClutterActor *stage;
|
||||
ClutterActor *texture;
|
||||
ClutterConstraint *constraint_x;
|
||||
ClutterConstraint *constraint_y;
|
||||
ClutterColor *pink;
|
||||
ClutterEffect *effect;
|
||||
gchar *filename;
|
||||
|
||||
if (argc < 2)
|
||||
{
|
||||
g_print ("Usage: %s <path to image file>\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
filename = argv[1];
|
||||
|
||||
clutter_init (&argc, &argv);
|
||||
|
||||
stage = clutter_stage_new ();
|
||||
clutter_actor_set_size (stage, 400, 400);
|
||||
g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL);
|
||||
|
||||
texture = clutter_texture_new ();
|
||||
clutter_texture_set_keep_aspect_ratio (CLUTTER_TEXTURE (texture), TRUE);
|
||||
clutter_actor_set_width (texture, 300);
|
||||
|
||||
/* NB ignoring missing file errors here for brevity */
|
||||
clutter_texture_set_from_file (CLUTTER_TEXTURE (texture),
|
||||
filename,
|
||||
NULL);
|
||||
|
||||
/* align the texture on the x and y axes */
|
||||
constraint_x = clutter_align_constraint_new (stage, CLUTTER_ALIGN_X_AXIS, 0.5);
|
||||
constraint_y = clutter_align_constraint_new (stage, CLUTTER_ALIGN_Y_AXIS, 0.5);
|
||||
clutter_actor_add_constraint (texture, constraint_x);
|
||||
clutter_actor_add_constraint (texture, constraint_y);
|
||||
|
||||
/* create a colorize effect with pink tint */
|
||||
pink = clutter_color_new (230, 187, 210, 255);
|
||||
effect = clutter_colorize_effect_new (pink);
|
||||
|
||||
/* apply the effect to the texture */
|
||||
clutter_actor_add_effect (texture, effect);
|
||||
|
||||
clutter_container_add_actor (CLUTTER_CONTAINER (stage), texture);
|
||||
|
||||
clutter_actor_show (stage);
|
||||
|
||||
clutter_main ();
|
||||
|
||||
return 0;
|
||||
}
|
119
doc/cookbook/examples/effects-custom-deform.c
Normal file
119
doc/cookbook/examples/effects-custom-deform.c
Normal file
@ -0,0 +1,119 @@
|
||||
/* Example of using a custom CbPageFoldEffect to do
|
||||
* an animated fold of a texture containing an image
|
||||
*
|
||||
* Pass the full path to the image on the command line;
|
||||
* click on the texture to trigger the folding animation
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
#include "cb-page-fold-effect.h"
|
||||
|
||||
static const ClutterColor stage_color = { 0x33, 0x33, 0x55, 0xff };
|
||||
|
||||
static gboolean
|
||||
button_pressed_cb (ClutterActor *actor,
|
||||
ClutterEvent *event,
|
||||
gpointer user_data)
|
||||
{
|
||||
ClutterState *transitions = CLUTTER_STATE (user_data);
|
||||
|
||||
if (g_strcmp0 (clutter_state_get_state (transitions), "folded") == 0)
|
||||
clutter_state_set_state (transitions, "unfolded");
|
||||
else
|
||||
clutter_state_set_state (transitions, "folded");
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc,
|
||||
char *argv[])
|
||||
{
|
||||
ClutterActor *stage;
|
||||
ClutterActor *texture;
|
||||
ClutterEffect *effect;
|
||||
ClutterState *transitions;
|
||||
GError *error = NULL;
|
||||
|
||||
gchar *filename;
|
||||
|
||||
if (argc < 2)
|
||||
{
|
||||
g_print ("Usage: %s <path to image file>\n", argv[0]);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
filename = argv[1];
|
||||
|
||||
clutter_init (&argc, &argv);
|
||||
|
||||
stage = clutter_stage_new ();
|
||||
clutter_actor_set_size (stage, 400, 300);
|
||||
clutter_stage_set_color (CLUTTER_STAGE (stage), &stage_color);
|
||||
g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL);
|
||||
|
||||
texture = clutter_texture_new ();
|
||||
clutter_texture_set_keep_aspect_ratio (CLUTTER_TEXTURE (texture), TRUE);
|
||||
clutter_actor_set_width (texture, 400);
|
||||
clutter_actor_set_reactive (texture, TRUE);
|
||||
clutter_texture_set_from_file (CLUTTER_TEXTURE (texture),
|
||||
filename,
|
||||
&error);
|
||||
|
||||
if (error != NULL)
|
||||
{
|
||||
g_critical ("Error loading texture from file %s; error was:\n%s",
|
||||
filename,
|
||||
error->message);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
/* create the page fold effect instance with destination fold angle
|
||||
* of 180 degrees and starting period of 0 (no folding)
|
||||
*/
|
||||
effect = cb_page_fold_effect_new (180.0, 0.0);
|
||||
|
||||
/* add the effect to the texture actor */
|
||||
clutter_actor_add_effect (texture, effect);
|
||||
|
||||
clutter_container_add_actor (CLUTTER_CONTAINER (stage), texture);
|
||||
|
||||
/* animation for the period property of the effect,
|
||||
* to animate its value between 0.0 and 1.0 and back
|
||||
*/
|
||||
transitions = clutter_state_new ();
|
||||
clutter_state_set_duration (transitions, NULL, NULL, 500);
|
||||
|
||||
clutter_state_set_duration (transitions,
|
||||
"partially-folded",
|
||||
"folded",
|
||||
375);
|
||||
|
||||
clutter_state_set (transitions, NULL, "folded",
|
||||
effect, "period", CLUTTER_LINEAR, 1.0,
|
||||
NULL);
|
||||
|
||||
clutter_state_set (transitions, NULL, "partially-folded",
|
||||
effect, "period", CLUTTER_LINEAR, 0.25,
|
||||
NULL);
|
||||
|
||||
clutter_state_set (transitions, NULL, "unfolded",
|
||||
effect, "period", CLUTTER_LINEAR, 0.0,
|
||||
NULL);
|
||||
|
||||
clutter_state_warp_to_state (transitions, "partially-folded");
|
||||
|
||||
g_signal_connect (texture,
|
||||
"button-press-event",
|
||||
G_CALLBACK (button_pressed_cb),
|
||||
transitions);
|
||||
|
||||
clutter_actor_show (stage);
|
||||
|
||||
clutter_main ();
|
||||
|
||||
g_object_unref (transitions);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
BIN
doc/cookbook/images/effects-built-in.png
Normal file
BIN
doc/cookbook/images/effects-built-in.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 90 KiB |
BIN
doc/cookbook/images/effects-custom-deform-back-material.png
Normal file
BIN
doc/cookbook/images/effects-custom-deform-back-material.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 49 KiB |
BIN
doc/cookbook/images/effects-custom-deform.png
Normal file
BIN
doc/cookbook/images/effects-custom-deform.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 90 KiB |
BIN
doc/cookbook/videos/effects-custom-deform.ogv
Normal file
BIN
doc/cookbook/videos/effects-custom-deform.ogv
Normal file
Binary file not shown.
Loading…
Reference in New Issue
Block a user