Animations Walt Disney Animation can explain whatever the mind of man can conceive.
Introduction Clutter actors have a variety of properties (position, size, rotation in 3D space, scale, opacity) which govern their visual appearance in the UI. They may also have constraints on how they are aligned and/or positioned relative to each other. The Clutter animation API provides a means of changing properties and constraints as a function of time: moving, scaling, rotating, changing opacity and colour, modifying postional constraints, etc. Clutter also makes it possible to animate non-visual properties if desired.
High level overview Here are the main concepts behind animation in Clutter: An animation changes one or more properties of one or more actors over time: their rotation in a particular dimension (x, y, z), scale, size, opacity etc. An animation has an associated timeline. Think of this as analogous to the "thing" you're controlling when you watch a video on the internet: it's what you control with the play/pause button and what is measured by the bar showing how far through the video you are. As with the controls on a video player, you can play/pause/skip a Clutter timeline; you can also rewind it, loop it, and play it backwards. If a timeline is reversed, the progress along the timeline is still measured the same way as it is in the forward direction: so if you start from the end of the timeline and run it backwards for 75% of its length, the progress is reported as 0.25 (i.e. 25% of the way from the start of the timeline). The duration of a timeline (e.g. 500 milliseconds, 1 second, 10 seconds) specifies how long its animation will last. The timeline can be inspected to find out how much of it has elapsed, either as a value in milliseconds or as a fraction (between 0 and 1) of the total length of the timeline. An animation is divided into frames. The number of frames which make up the animation isn't constant: it depends on various factors, like how powerful your machine is, the state of the drivers for your hardware, and the load on he system. So you won't always get the same number of frames in an animation of a particular duration. The change to a property in an animation occurs over the course of the timeline: the start value of the property heads toward some target value. When it reaches the end of the timeline, the property should have reached the target value. Exactly how the property changes over the course of the timeline is governed by an alpha. This is the trickiest idea to explain, so it has its own section below.
Alphas An alpha is generated for each frame of the animation. The alpha varies between -1.0 and 2.0, and changes during the course of the animation's timeline; ideally, the value should start at 0.0 and reach 1.0 by the end of the timeline. The alpha for any given frame of the animation is determined by an alpha function. Usually, the alpha function will return a value based on progress along the timeline. However, the alpha function doesn't have to respect or pay attention to the timeline: it can be entirely random if desired. To work out the value of a property at a given frame somewhere along the timeline for a given alpha: Determine the difference between the start value and the target end value for the property. Multiply the difference by the alpha for the current frame. Add the result to the start value. The shape of the plot of the alpha function over time is called its easing mode. Clutter provides various modes ranging from CLUTTER_LINEAR (the alpha value is equal to progress along the timeline), to modes based on various polynomial and exponential functions, to modes providing elastic and bounce shapes. See the ClutterAlpha documentation for examples of the shapes produced by these functions. There is also a good interactive demo of the modes on Robert Penner's site. Most of the time, you can use the built-in Clutter easing modes to get the kind of animation effect you want. However, in some cases you may want to provide your own alpha function. Here's an example (based on the quintic ease in mode from clutter-alpha.c): An alpha function just has to have a specified method signature and return a gdouble value when called. As stated above, you'd typically base the return value on the timeline progress; the function above shows how you get the timeline associated with the alpha, so you can apply the alpha function to it.
Clutter's animation API All of the animation approaches in Clutter use the same basic underpinnings (as explained above), but the API provides varying levels of abstraction and/or ease of use on top of those underpinnings. Implicit animations (created using clutter_actor_animate() and related functions) are useful where you want to apply a simple or one-off animation to an actor. They enable you to animate one or more properties using a single easing mode; however, you only specify the target values for the properties you're animating, not the start values. ClutterAnimator provides support for declarative animations (defined using ClutterScript). You can animate multiple actors with this approach, and have more control over the easing modes used during an animation: while implicit animations only allow a single easing mode for all properties, ClutterAnimator supports multiple easing modes for each property; key frames are used to indicate where in the animation each easing mode should be applied. ClutterState enables you to describe states: property values across one or more actors, plus the easing modes used to transition to those values. It can also be combined with ClutterAnimator for finer grained definition of transitions if desired. States are particularly useful if you need actors to animate between a known set of positions/sizes/opacities etc. during their lifecycles (e.g. animating a list of items in a menu, or for animations in a picture viewer where you click on thumbnails to display a full view of a photograph). The recipes in this section show when and where it is appropriate to use each of these approaches.
Inverting Animations
Problem You want to have an animation exactly mirroring another one that you just played.
Solution Reverse the direction of the ClutterTimeline associated with the animation. For example, here's how to invert an implicit animation which moves an actor along the x axis. The direction of the animation is inverted when the movement along the x axis is completed; it is also inverted if the mouse button is pressed on the actor. First, set up the animation: Next, add a function for inverting the timeline: Then add a function which calls _invert_timeline when the animation completes. More importantly, the callback should stop emission of the "completed" signal by the animation. This prevents the ClutterAnimation underlying the implicit animation from being unreferenced; which in turn allows it to be inverted: Finally, the click callback function uses the same _invert_timeline function if the animation is playing; but if the animation is stopped, it will start it instead:
Discussion If you are using ClutterAnimator rather than implicit animations, clutter_animator_get_timeline() enables you to get the underlying timeline; you could then use the techniques shown above to invert it. ClutterState enables a different approach to "inverting" an animation: rather than having a single animation which you invert, you would define two or more keys for an actor (or set of actors) and transition between them. For the example above, you would define two keys: one for the actor's initial position; and a second for the actor at x = 300.0. You would also define the transition between them: 2000 milliseconds with a CLUTTER_EASE_IN_OUT_CUBIC easing mode. With the states defined, you would then use clutter_state_set_state() inside callbacks to animate the actor between the two x positions. Behind the scenes, ClutterState would handle the animations and timelines for you.
Fading an actor out of or into view
Problem You want to animate an actor so that it fades out of or into view.
Solution Animate the actor's opacity property. You can do this using any of the approaches provided by the animation API. Here's how to fade out an actor (until it's completely transparent) using implicit animations: Here's an example of a rectangle fading out using this animation: Video showing an actor fading out using implicit animations CLUTTER_EASE_OUT_CUBIC is one of the Clutter easing modes; see the introduction for more details about what these are and how to choose one. Here's an example of the transitions you could use to fade an actor in and out using ClutterState: You would then trigger an animated state change as events occur in the application (e.g. mouse button clicks): Here's an example of this animation fading in then out again: Video showing an actor fading in then out using ClutterState ClutterState is most useful where you need to animate an actor backwards and forwards between multiple states (e.g. fade an actor in and out of view). Where you just want to fade an actor in or out once, clutter_actor_animate() is adequate.
Discussion Reducing an actor's transparency to zero does not make it inactive: the actor will still be reactive even if it's not visible (responding to key events, mouse clicks etc.). To make it really "disappear", you could use clutter_actor_hide() once you'd made the actor fully transparent.
Rotating an actor
Problem You want to animate rotation of an actor. Some example cases where you might want to do this: To rotate an image so it's the right way up for viewing. To make actors more or less prominent, rotating them towards or away from the view point. To turn an actor "around" and display different UI elements "behind" it.
Solution Animate one of the rotation-angle-(x|y|z) properties of the actor. The most "obvious" (and probably most commonly used) rotation is in the z axis (parallel to the 2D surface of the UI). The other rotation axes (x and y) are less obvious, as they rotate the actor in the depth dimension, "away from" or "towards" the view point. Examples of each type of rotation are given below. While the examples use implicit animations, it is also possible to use ClutterAnimator and ClutterState to animate rotations: see the full example at the end of this recipe for some ClutterState code. I've added an inaccurate (but hopefully useful) metaphor to each rotation axis ("wheel", "letter box", "door"), to make it easier to remember the effect you get from animating in that axis (and when the rotation center is inside the actor). Rotating on the z axis ("wheel") The above code animating a texture: Video showing an actor rotating to 90 degrees on the z axis By default, the center of the rotation is derived from the anchor point of the actor; unless you've changed the anchor point, the default is the top-left corner of the actor. See the Discussion section below for more about setting the rotation center. An animated rotation moves an actor to the specified rotation angle; it does not increment or decrement the actor's current rotation angle by the amount specified. Rotating on the x axis ("letter box") The above code animating a texture: Video showing an actor rotating to -45 degrees on the x axis Notice how the texture rotates away from the view point, and also how perspective effects are applied (as the actor is rotating "into" the depth dimension). Rotating on the y axis ("door") The above code animating a texture: Video showing an actor rotating to 45 degrees on the y axis Again, the rotation is into the depth dimension, so you get perspective effects.
Discussion It can sometimes be difficult to predict exactly how a particular rotation animation will appear when applied. Often the only way to find out is to experiment. However, the sections below outline some of the most common factors which affect animated rotations, with the aim of minimising the experimentation you need to do.
Setting the rotation center for an animation The examples in the previous section used the default center of rotation for each axis. However, it is possible to change the rotation center for an axis, in turn changing the appearance of the animation. Rotation center coordinates are relative to the actor's coordinates, not to the coordinates of the actor's container or the stage.
Setting a rotation center inside an actor You can set the center for rotation on the x or y axes like this: Because z axis rotations are more common, Clutter provides some convenience functions to set the rotation center for this axis: CLUTTER_GRAVITY_CENTER makes the center of the actor the rotation center for the z axis. See the ClutterGravity enumeration for acceptable values for this parameter. Setting the rotation center for the z axis using gravity is recommended, as Clutter will automatically recompute the rotation center if the actor's size changes. For the x and y axes, you have to do this computation yourself if you want an actor's center of rotation to stay in the same place if it is resized. Rotation on the x axis around an actor's center: Video showing an actor rotating around its center on the x axis Rotation on the y axis around an actor's center: Video showing an actor rotating around its center on the y axis Rotation on the z axis around an actor's center: Video showing an actor rotating around its center on the z axis
Setting the rotation center outside an actor Rather than rotating the actor around a point inside itself, the rotation center can be moved to a position outside the actor. (In the case of the z axis, any rotation center setting is outside the actor as its depth is 0.) When animated, the actor will describe an arc around the rotation center, as if it's swinging from an invisible thread. The same code as shown above can be used to set the rotation center: just set the rotation center coordinates to negative numbers (outside the actor). However, you can't use the gravity functions if the rotation center falls outside an actor. For example, here's a rotation to -180 degrees in the x axis, with the y rotation center set to -96 (the same as the height of the actor): Video showing an actor rotating to -180 degrees on the x axis with y rotation center set to -96 Similarly, moving the z rotation center (for a rotation in the x or y axis) will cause the actor to swing "into" or "out of" the UI. Its final apparent size may be different, as it could reach a different depth in the UI by the end of the animation. For example, here's a rotation to -180 in the x axis, with the z rotation center set to -96 (the same as the height of the actor): Video showing an actor rotating to -180 degrees on the x axis with z rotation center set to -96 The apparent final size of the actor is reduced, as it has rotated away from the view point.
Direction of rotation The apparent direction of an animated rotation depends on two things: Whether the angle of rotation is positive or negative. The rotation of the container(s) the actor is inside. In the case of the sign of the rotation, here's what happens for each axis and rotation angle sign (positive or negative). Axis Sign of rotation angle Effect on actor z + Clockwise spin about the x,y center of rotation. z - Anti-clockwise spin about the x,y center of rotation. x + The top swings away from the view point and the bottom swings towards it. If y rotation center == 0, the top is fixed; if y rotation center == the actor's height, the bottom is fixed. x - The bottom swings away from the view point and the top swings towards it. If y rotation center == 0, the top is fixed; if y rotation center == the actor's height, the bottom is fixed. y + The right-hand side swings away from the view point and the left-hand side swings towards it. When x rotation center == 0, the left-hand side if fixed; when x rotation center == the actor's width, the right-hand side is fixed. y - The right-hand side swings towards the view point and the left-hand side swings away from it. When x rotation center == 0, the left-hand side if fixed; when x rotation center == the actor's width, the right-hand side is fixed. If an actor's container is rotated, this may affect the appearance of rotation animations applied to the actor. In particular, if an actor's container has been rotated by 180 degrees in one axis, the direction of that actor's rotation may appear reversed. For example, the video below shows an actor being animated to 90 degrees on the z axis, then back to 0 degrees; the actor's container is then rotated by 180 degrees in the y axis; then the same rotation 90 degree rotation is applied to the actor again. Note that the first time the animation is applied, the rotation is clockwise; but the second time (as the actor is effectively "reversed"), it is anti-clockwise. Video showing how an actor's apparent rotation is affected by the rotation of its parent
Apparent vs. actual rotation There is a difference between an actor's apparent rotation (how much an actor appears to be rotating, from the perspective of someone looking at the UI) and its actual rotation (how much that actor is really rotating). For example, if you rotate an actor and its container simultaneously, each by 90 degrees in the same direction, the actor will appear to have rotated by 180 degrees by the end of the animation. However, calling the clutter_actor_get_rotation() function for that axis on the actor still returns a rotation of 90 degrees.
Orientation of rotation axes The rotation axes remain fixed in the same place on the actor regardless of its rotation, even though from the viewer's perspective they may appear to move. For example, when rotation in the z axis is 0 degrees, the actor's x axis is horizontal (across the UI) from both the actor's and the viewer's perspective. However, if you rotate the actor by 90 degrees in the z axis, the x axis is now vertical from the viewer's perspective, but still horizontal across the actor from the actor's perspective.
Full example Rotating an actor around x, y, and z axes using <type>ClutterState</type> a code sample should be here... but isn't