mirror of
https://github.com/brl/mutter.git
synced 2024-12-23 19:42:05 +00:00
docs: Remove the old animation tutorial
The animation tutorial was written in the Good Ol' 0.x days, and has barely been updated during the 1.x cycle; it only referenced low level or deprecated API, and the ClutterActor class description has a whole section on how to animate actors using both the implicit and the explicit animation API.
This commit is contained in:
parent
7043a3a1ed
commit
4c1bf6162a
@ -139,7 +139,6 @@ SVG_IMAGES = \
|
||||
# e.g. content_files=running.sgml building.sgml changes-2.0.sgml
|
||||
content_files = \
|
||||
glossary.xml \
|
||||
clutter-animation-tutorial.xml \
|
||||
clutter-overview.xml \
|
||||
building-clutter.xml \
|
||||
running-clutter.xml \
|
||||
@ -152,7 +151,6 @@ content_files = \
|
||||
# e.g. expand_content_files=running.sgml
|
||||
expand_content_files = \
|
||||
glossary.xml \
|
||||
clutter-animation-tutorial.xml \
|
||||
clutter-overview.xml \
|
||||
building-clutter.xml \
|
||||
running-clutter.xml \
|
||||
|
@ -1,466 +0,0 @@
|
||||
<chapter id="clutter-animations">
|
||||
<chapterinfo>
|
||||
<author>
|
||||
<firstname>Matthew</firstname>
|
||||
<surname>Allum</surname>
|
||||
<affiliation>
|
||||
<address>
|
||||
<email>mallum@openedhand.com</email>
|
||||
</address>
|
||||
</affiliation>
|
||||
</author>
|
||||
|
||||
<author>
|
||||
<firstname>Emmanuele</firstname>
|
||||
<surname>Bassi</surname>
|
||||
<affiliation>
|
||||
<address>
|
||||
<email>ebassi@linux.intel.com</email>
|
||||
</address>
|
||||
</affiliation>
|
||||
</author>
|
||||
</chapterinfo>
|
||||
|
||||
<title>Creating Animations with Clutter</title>
|
||||
|
||||
<para>With Clutter using hardware accelration for graphics rendering,
|
||||
complex and fast animations are possible. This chapter describes basic
|
||||
techniques and the utilities Clutter provides in aiding animation
|
||||
creation.</para>
|
||||
|
||||
<section id="clutter-animation-basic">
|
||||
<title>Basic Animations</title>
|
||||
|
||||
<para>The most basic way to create animations with Clutter is via the use
|
||||
of clutter_threads_add_timeout(). This enables a callback function to be
|
||||
called at a defined interval. The callback function can then modify actors
|
||||
visual properties as to produce an animation.</para>
|
||||
|
||||
<example id="clutter-timeout-example">
|
||||
<title>Simple timeout example</title>
|
||||
<para>Implement a rotating actor using 360 "frames"</para>
|
||||
<programlisting>
|
||||
struct RotationClosure {
|
||||
ClutterActor *actor;
|
||||
|
||||
gdouble final_angle;
|
||||
gdouble current_angle;
|
||||
};
|
||||
|
||||
static gboolean
|
||||
rotate_actor (gpointer data)
|
||||
{
|
||||
struct RotationClosure *clos = data;
|
||||
|
||||
clutter_actor_set_rotation (clos->actor, clos->current_angle, 0, 0, 0);
|
||||
|
||||
/* add one degree */
|
||||
clos->current_angle += 1.0
|
||||
|
||||
/* if we reached the target angle, stop */
|
||||
if (clos->current_angle == clos->final_angle)
|
||||
return G_SOURCE_REMOVE;
|
||||
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
|
||||
static void
|
||||
rotate_actor_cleanup (gpointer data)
|
||||
{
|
||||
struct RotationClosure *clos = data;
|
||||
|
||||
g_object_unref (clos->actor);
|
||||
g_free (clos);
|
||||
}
|
||||
|
||||
...
|
||||
struct RotationClosure *clos = NULL;
|
||||
|
||||
clos = g_new (struct RotationClosure, 1);
|
||||
clos->actor = g_object_ref (an_actor);
|
||||
clos->final_angle = 360.0;
|
||||
clos->current_angle = 0;
|
||||
|
||||
clutter_threads_add_timeout_full (G_PRIORITY_DEFAULT,
|
||||
1000 / 360, /* 360 updates in one second */
|
||||
rotate_actor,
|
||||
clos,
|
||||
rotate_actor_cleanup);
|
||||
</programlisting>
|
||||
</example>
|
||||
|
||||
<note>
|
||||
<title>Priorities</title>
|
||||
<para>%G_PRIORITY_DEFAULT should always be used as the timeouts priority
|
||||
(in case of clutter_threads_add_timeout_full()) as not to intefere with
|
||||
Clutter's scheduling of repaints and input event handling.</para>
|
||||
</note>
|
||||
</section>
|
||||
|
||||
<section id="clutter-animation-timelines">
|
||||
<title>Timelines</title>
|
||||
|
||||
<para>Using clutter_threads_add_timeout() to control an animation is
|
||||
complicated and does not work in concert with the rest of the operations
|
||||
Clutter must perform for each redraw cycle.</para>
|
||||
|
||||
<para>For this reason, Clutter provides #ClutterTimeline, a class that
|
||||
allows scheduling animations with a definite duration. Timelines are
|
||||
advanced during the redraw cycle so that animations are ready to be
|
||||
performed at the right time. This also means that animations will not
|
||||
affect the event processing; it also means that if the animation is too
|
||||
complex it will be called with a longer delay, thus not blocking the
|
||||
whole UI.</para>
|
||||
|
||||
<para>A Timeline is created with:</para>
|
||||
|
||||
<programlisting>
|
||||
ClutterTimeline *timeline = clutter_timeline_new (duration_in_milliseconds);
|
||||
</programlisting>
|
||||
|
||||
<para>The duration of the timeline then be modifed via the
|
||||
#ClutterTimeline:duration property or by using
|
||||
clutter_timeline_set_duration().</para>
|
||||
|
||||
<para>A timeline is started via clutter_timeline_start() and its
|
||||
playback further manipulated by the clutter_timeline_pause(),
|
||||
clutter_timeline_stop(), clutter_timeline_rewind() and
|
||||
clutter_timeline_skip() functions.</para>
|
||||
|
||||
<para>By attaching a handler to the timeline's
|
||||
#ClutterTimeline::new-frame signal a timeline can then be used to
|
||||
drive an animation by altering an actor's visual properties. The
|
||||
callback looks like:</para>
|
||||
|
||||
<programlisting>
|
||||
void
|
||||
on_new_frame (ClutterTimeline *timeline,
|
||||
gint elapsed_msecs,
|
||||
gpointer user_data)
|
||||
{
|
||||
}
|
||||
</programlisting>
|
||||
|
||||
<para>The <literal>elapsed_msecs</literal> parameter is set to the amount
|
||||
of time elapsed since the beginning of the timeline, and its value is
|
||||
always between 0 and the #ClutterTimeline:duration value.</para>
|
||||
|
||||
<para>The function clutter_timeline_get_progress() can also be used to
|
||||
get a normalised value of the timeline's current position between 0 and
|
||||
1.</para>
|
||||
|
||||
<para>Timelines can also be played in reverse by setting the direction
|
||||
using clutter_timeline_set_direction(), and can also have a one-time
|
||||
delay set before they begin playing by using the function
|
||||
clutter_timeline_set_delay().</para>
|
||||
|
||||
<para>Timelines can also control a pyshical simulation; the
|
||||
clutter_timeline_get_delta() function allows retrieving the number of
|
||||
milliseconds elapsed since the previous callback to ensure the physics
|
||||
engine to be able to take the actual time elapsed between iterations
|
||||
into account.</para>
|
||||
|
||||
<example id="clutter-timeline-example">
|
||||
<title>Using a Timeline to drive an animation</title>
|
||||
<para>Rewrite the example above with a #ClutterTimeline instead of
|
||||
using clutter_threads_add_timeout()</para>
|
||||
<programlisting>
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
static void
|
||||
on_new_frame (ClutterTimeline *timeline,
|
||||
gint elapsed_msecs,
|
||||
ClutterActor *actor)
|
||||
{
|
||||
gdouble angle = 360 * clutter_timeline_get_progress (timeline);
|
||||
|
||||
clutter_actor_set_rotation (actor, CLUTTER_Z_AXIS,
|
||||
angle,
|
||||
clutter_actor_get_width (actor) / 2,
|
||||
clutter_actor_get_height (actor) / 2,
|
||||
0);
|
||||
}
|
||||
|
||||
...
|
||||
|
||||
ClutterTimeline *timeline;
|
||||
|
||||
/* one second */
|
||||
timeline = clutter_timeline_new (1000);
|
||||
|
||||
/* looping indefinitely */
|
||||
clutter_timeline_set_repeat_count (timeline, -1);
|
||||
|
||||
/* get a notification each time a new frame should be drawn */
|
||||
g_signal_connect (timeline, "new-frame", G_CALLBACK (on_new_frame), actor);
|
||||
|
||||
/* start the timeline once control returns to the main loop */
|
||||
clutter_timeline_start (timeline);
|
||||
</programlisting>
|
||||
</example>
|
||||
</section>
|
||||
|
||||
<!-- XXX - Behaviours are deprecated
|
||||
<section id="clutter-animation-behaviours">
|
||||
<title>Behaviours</title>
|
||||
<para>With a large application containing many animations, the use of
|
||||
just timelines can become unwieldy and difficult to manage, with much
|
||||
code duplication in the #ClutterTimeline::new-frame handlers that can
|
||||
require over-complex code changes for minor animation modifications. To
|
||||
ease these problems the #ClutterAlpha and #ClutterBehaviour classes were
|
||||
created.</para>
|
||||
|
||||
<para>#ClutterAlpha and #ClutterBehaviour attempt to generalise the
|
||||
#ClutterTimeline::new-frame function by defining common actions (or
|
||||
behaviours) that can be quickly modified, applied to multiple actors or
|
||||
mixed on a single actor.</para>
|
||||
|
||||
<para>A #ClutterAlpha is a 'function of time' (and does not refer to the
|
||||
alpha channel of a RGBA color). It is created by referencing a source
|
||||
timeline and an "easing mode" whichproduces a value between -1.0 and 2.0
|
||||
depending on the progress of the timeline. Clutter provides various
|
||||
easing modes, as described by the #ClutterAnimationMode enumeration. It is
|
||||
also possible to register new animation modes using the function
|
||||
clutter_alpha_register_func() or to provide a custom #ClutterAlphaFunc for
|
||||
a specific #ClutterAlpha instance.</para>
|
||||
|
||||
<para>A #ClutterBehaviour is created with a #ClutterAlpha and a set of
|
||||
parameters for whatever the behaviour modifies in an actor. The value of
|
||||
a #ClutterAlpha during the animation is then mapped to a value for the
|
||||
behaviour parameters and then applied on the actors referenced by the
|
||||
#ClutterBehaviour. With the #ClutterAlpha's underlying timeline playing
|
||||
the produced value will change and the behaviour will animate an
|
||||
actor.</para>
|
||||
|
||||
<para>A #ClutterBehaviour is effectively 'driven' by a supplied
|
||||
#ClutterAlpha and when then applied to an actor it will modify a visual
|
||||
property or feature of the actor dependant on the Alpha's value. For
|
||||
example, a path-based behaviour applied to an actor will alter its
|
||||
position along a #ClutterPath, depending on the current alpha value over
|
||||
time. The actual progress of the motion will depend on the chosen "easing
|
||||
mode".</para>
|
||||
|
||||
<para> Multiple behaviours can of course be applied to an actor as well
|
||||
as a single behaviour being applied to multiple actors. The separation
|
||||
of timelines, alphas and behaviours allows for a single timeline to drive
|
||||
many behaviours each potentially using different alpha functions.
|
||||
Behaviour parameters can also be changed on the fly.</para>
|
||||
|
||||
<para>
|
||||
<figure id="behaviour-path-alpha">
|
||||
<title>Effects of alpha functions on a path</title>
|
||||
<graphic fileref="path-alpha-func.png" format="PNG"/>
|
||||
<blockquote>The actors position between the path's end points
|
||||
directly correlates to the #ClutterAlpha's current alpha value
|
||||
driving the behaviour. With the #ClutterAlpha's animation mode
|
||||
set to %CLUTTER_LINEAR the actor will follow the path at a constant
|
||||
velocity, but when changing to %CLUTTER_EASE_IN_OUT_SINE the actor
|
||||
initially accelerates before quickly decelerating.</blockquote>
|
||||
</figure>
|
||||
</para>
|
||||
|
||||
<para>The behaviours included in Clutter are:</para>
|
||||
|
||||
<para>
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term>#ClutterBehaviourDepth</term>
|
||||
<listitem><simpara>Changes the depth of actors</simpara></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>#ClutterBehaviourEllipse</term>
|
||||
<listitem><simpara>Moves actors along an elliptical path</simpara></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>#ClutterBehaviourOpacity</term>
|
||||
<listitem><simpara>Changes the opacity of actors</simpara></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>#ClutterBehaviourPath</term>
|
||||
<listitem><simpara>Moves actors along a path</simpara></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>#ClutterBehaviourRotate</term>
|
||||
<listitem><simpara>Rotates actors along an axis</simpara></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>#ClutterBehaviourScale</term>
|
||||
<listitem><simpara>Changes the scaling factors of actors</simpara></listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</para>
|
||||
|
||||
<example id="clutter-behaviour-example">
|
||||
<title>Using a #ClutterBehaviour</title>
|
||||
<para>The following example demonstrates an ellipse behaviour in
|
||||
action.</para>
|
||||
<programlisting>
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
ClutterTimeline *timeline;
|
||||
ClutterBehaviour *behave;
|
||||
ClutterAlpha *alpha;
|
||||
ClutterActor *stage, *actor;
|
||||
|
||||
if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS)
|
||||
return 1;
|
||||
|
||||
stage = clutter_stage_new ();
|
||||
g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL);
|
||||
|
||||
actor = clutter_texture_new_from_file ("ohpowers.png", NULL);
|
||||
clutter_container_add_actor (CLUTTER_CONTAINER (stage), actor);
|
||||
|
||||
/* set up the animation to be 4 seconds long, and looping indefinitely */
|
||||
timeline = clutter_timeline_new (4000);
|
||||
clutter_timeline_set_repeat_count (timeline, -1);
|
||||
|
||||
/* set up a sinusoidal easing mode to power the behaviour; the
|
||||
* alpha will take a reference on the timeline so we can safely
|
||||
* release the reference we hold
|
||||
*/
|
||||
alpha = clutter_alpha_new_full (timeline, CLUTTER_EASE_IN_OUT_SINE);
|
||||
g_object_unref (timeline);
|
||||
|
||||
/* the behaviour will own the alpha by sinking its floating
|
||||
* reference (if needed)
|
||||
*/
|
||||
behave = clutter_behaviour_ellipse_new (alpha,
|
||||
200, /* center x */
|
||||
200, /* center y */
|
||||
400, /* width */
|
||||
300, /* height */
|
||||
CLUTTER_ROTATE_CW, /* direction */
|
||||
0.0, /* initial angle */
|
||||
360.0); /* final angle */
|
||||
|
||||
clutter_behaviour_apply (behave, actor);
|
||||
|
||||
clutter_actor_show_all (stage);
|
||||
|
||||
clutter_timeline_start (timeline);
|
||||
|
||||
clutter_main();
|
||||
|
||||
/* clean up; behaviours are top-level objects */
|
||||
g_object_unref (behave);
|
||||
|
||||
return 0;
|
||||
}
|
||||
</programlisting>
|
||||
</example>
|
||||
|
||||
<note><para>The parameters of a #ClutterBehaviour can be changed whilst
|
||||
a animation is running.</para></note>
|
||||
|
||||
<para>There can be many #ClutterAlpha's attached to a single timeline.
|
||||
There can be many behaviours for a #ClutterAlpha. There can be many
|
||||
behaviours applied to an actor. A #ClutterScore can be used to chain
|
||||
many behaviours together.</para>
|
||||
|
||||
<warning><para>Combining behaviours that effect the same actor properties
|
||||
(i.e two separate paths) will cause unexpected results. The values will
|
||||
not be merged in any way with only the last applied behaviour taking
|
||||
precedence.</para></warning>
|
||||
|
||||
<note><para>Tips for implementing a new behaviour can be found <link
|
||||
linkend="creating-your-own-behaviours">here</link>.</para></note>
|
||||
|
||||
</section>
|
||||
-->
|
||||
|
||||
<section id="clutter-animation-implicit">
|
||||
<title>Implicit Animations</title>
|
||||
|
||||
<para>Using behaviours for simple animations of a single actor may
|
||||
be too complicated, in terms of memory management and bookkeeping
|
||||
of the object instances. For this reason, Clutter also provides a
|
||||
simple animation API for implicit animations using properties of
|
||||
an actor: clutter_actor_animate().</para>
|
||||
|
||||
<para>The clutter_actor_animate() family of functions will create
|
||||
and use an implicit #ClutterAnimation instance, which will then
|
||||
handle the animation of one or more #ClutterActor properties between
|
||||
a range of values.</para>
|
||||
|
||||
<example id="clutter-actor-animate-example">
|
||||
<title>Using clutter_actor_animate()</title>
|
||||
<para>The following example demonstrates how to use the
|
||||
clutter_actor_animate() method to tween an actor between the current
|
||||
position and a new set of coordinates. The animation takes 200
|
||||
milliseconds to complete and uses a linear progression.</para>
|
||||
<programlisting>
|
||||
clutter_actor_animate (actor, CLUTTER_LINEAR, 200,
|
||||
"x", 200.0f,
|
||||
"y", 200.0f,
|
||||
NULL);
|
||||
</programlisting>
|
||||
</example>
|
||||
|
||||
<para>The clutter_actor_animate() method returns a #ClutterAnimation
|
||||
instance that can be used to start, stop and modify the animation
|
||||
while it's running. The #ClutterAnimation::completed signal will
|
||||
be emitted when the animation has been completed.</para>
|
||||
|
||||
<warning><para>When the animation is complete it will be automatically
|
||||
unreferenced, and disposed if nothing else is holding a reference
|
||||
on it.</para></warning>
|
||||
|
||||
<example id="clutter-actor-animate-multi-example">
|
||||
<title>Animating inside an event handler</title>
|
||||
<para>The following example demonstrates how to animate an actor
|
||||
inside the signal handler for a button press event. If the user
|
||||
presses the button on a new position while the animation is running,
|
||||
the animation will be restarted with the new final values
|
||||
updated.</para>
|
||||
<programlisting>
|
||||
static gboolean
|
||||
on_button_press (ClutterActor *actor,
|
||||
ClutterEvent *event,
|
||||
gpointer user_data)
|
||||
{
|
||||
gfloat event_x, event_y;
|
||||
|
||||
clutter_event_get_coords (event, &event_x, &event_y);
|
||||
clutter_actor_animate (actor, CLUTTER_EASE_SINE_OUT, 500,
|
||||
"x", event_x,
|
||||
"y", event_y,
|
||||
NULL);
|
||||
return TRUE;
|
||||
}
|
||||
</programlisting>
|
||||
</example>
|
||||
|
||||
<para>Calling clutter_actor_animate() multiple times on an
|
||||
actor which is being animated will cause the animation to be updated
|
||||
with the new values.</para>
|
||||
|
||||
<para>If you need to chain up multiple animations created using
|
||||
clutter_actor_animate() you should connect to the
|
||||
#ClutterAnimation::completed signal using g_signal_connect_after()
|
||||
to have the guarantee that the current #ClutterAnimation has been
|
||||
detached from the actor. The documentation for clutter_actor_animate()
|
||||
has further examples.</para>
|
||||
|
||||
</section>
|
||||
|
||||
<section id="clutter-animation-conclusion">
|
||||
<title>Conclusion</title>
|
||||
<para>Clutter provides a number of utility classes to aid animations
|
||||
and complex animations can be produced by combining the various features
|
||||
provided.</para>
|
||||
|
||||
<para>Of course animations can becreated outside of the Clutter animation
|
||||
framework, as the framework is not expected to cover every kind of
|
||||
possible animation scenario.</para>
|
||||
|
||||
<para>The animation functionality in Clutter is primarily suited to
|
||||
building animations with a set or finite running time - i.e transitions
|
||||
between states. For animations involving variable input (such as
|
||||
touchscreen handling) physical simulations may be more suited.</para>
|
||||
</section>
|
||||
|
||||
</chapter>
|
@ -222,17 +222,6 @@
|
||||
<xi:include href="xml/clutter-wayland-surface.xml"/>
|
||||
</part>
|
||||
|
||||
<part id="additionaldocs">
|
||||
<title>Additional Documentation</title>
|
||||
|
||||
<partintro>
|
||||
<para>This section contains additional useful documentation for
|
||||
developing with Clutter.</para>
|
||||
</partintro>
|
||||
|
||||
<xi:include href="xml/clutter-animation-tutorial.xml"/>
|
||||
</part>
|
||||
|
||||
<part id="migration">
|
||||
<title>Migrating from previous version of Clutter</title>
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user