Experiments with clutter

A recurring theme at this years Guadec was the need for a toolkit next to Gtk+ for doing some of the next generation fancy effects that Gtk+ isn’t suited to (i.e. things like coverflow). One of the current experimental approaches for this is Clutter. In order to get a feel for clutter and the requirements and usecases for a toolkit supporting fancy effects I started writing a small demo for a fancy version of a gdm greeter. Its basically a fullscreen face-browser in the form of a Rolodex:

screenshot of fancy-greeter

I did all development on a machine without 3D acceleration (way to go ATI! I’ll never buy your hardware again), and it does work with the Mesa software rasterizer, but its really meant to be running on a 3D accelerated machine, and that is where it looks and behaves nice.

If you want to test it out, the code is available via git at http://www.gnome.org/~alexl/git/fancy-greeter.git/ . You need clutter and clutter-cairo from svn too.

As to clutter, It seems very nice. I got a bunch of OpenGL error spew when removing actors errors that I don’t believe is my fault, so it seems to have some bugs, but it was easy for me to hack up this example in a few hours, so the API is easy to use. I’m not completely sold on the animation framework though, it seems a little hard to use. Hopefully with the competition from other projects like pigment we’ll figure out the best API for this eventually.

10 Responses to “Experiments with clutter”

  1. Ross Burton says:

    Go Alex go!

    Go and file a bug for the GL warnings, so we don’t forget to look at that (bugzilla.openedhand.com).

    Your next mission is to make the fancy-greeter use the new gdm3 dbus api. ;)

  2. mallum says:

    Cool stuff, thanks for taking the time to play with clutter and for filing bugs.

    Re the animation framework, do you have any thoughts or ideas here on what could work better ? I agree the current stuff is a little complex in getting to grips with initially but once learnt it should be pretty powerful. Maybe just better documentation is whats needed here ?

  3. alexl says:

    I think the implicit animation work MacSlow was talking about sounded better.
    Essentially you give the target state, how long the transition should take, and then some sort of description of how the transition should work (ramp, sine, damped, etc). Then the animation framework handles the rest for you.

    Where this is nicer is when you have a current animation already happening, and you set a new target state and time for that to be done. The animation system can then automatically handle this, even though the first animation isn’t done, and the fact that the two animations overlap (partiallyI) in time.

    But i haven’t given this any deeper thought.

  4. Emmanuele says:

    alexl: what you want are behaviours or, if you just need to animate a single actor once, the clutter-effect API. the former is more complex but gives you a great deal of control on how the animation should look and behave; the latter are dead simple and useful for one-shot effects. those are the implicit animation facilities that clutter has.

  5. mallum says:

    hmm, I think we need documentation as iirc what you describe you can already do. i.e; transition time -> timeline, how animation works -> alpha, what state it affects and its start/end state -> behaviour. You can of course change any of the following on the fly (via props on behaviour/alpha/timeline objects).

  6. alexl says:

    Ok, say I’m rotating a menu. Its currently at 0 degrees.
    When I press the button I want to start a rotation that (with a smoth framerate) ends up at 45 degrees after 3 seconds.
    However, before the animation is done (say after one second, with angle now being 15 degrees) the use presses the key again. The target is now the target is 90 degrees, in 3 seconds (i.e. 4 seconds after the initial key hit). This means the rotation needs to speed up to keep up. It should not first finish the first animation and then do the second, nor should it drop the first, start at 45 degrees and then continue to 90.

    So, how would I do this in clutter?

  7. mallum says:

    okeys, so something like:

    create a timeline, a ramp like alpha and then a rotation behaviour with
    this timeline and alpha. This behaviour would have a start angle of 0 degrees and an end angle of 45 degrees. You’d then apply this behaviour to the menu actor and start the timeline (which starts the behaviour) on a button press. This would then start the animation.

    If the button is hit again, you can check if the animation is running (clutter_timeline_is_playing ()) and if so just set the rotation behaviours ‘angle-end’ prop to 90 degrees. Thats it, the timeline and behaviour machinery will deal with it then rotating faster to reach 90 degrees in remaining frames.

    If this doesn’t work its a bug in the rotation behaviour which will be quickly fixed :)

  8. alexl says:

    Don’t you also need to change the end time of the timeline?
    And can you get the timeline from the actor, or do i have to keep it around myself?

  9. mallum says:

    Assuming you want the total time of the animation to stay the same you shouldn’t need to change the timelines length (but you could change it on the fly if you want it, its another prop).

    You can get the actors a behaviour is applied to via clutter_behaviour_actors_foreach () or clutter_behaviour_get_actors () . You can get a timeline from a behaviour via getting the alpha – clutter_behaviour_get_alpha() and then the timeline from that – clutter_alpha_get_timeline (). I know this seems a bit convoluted but it seems mostly the timelines get kept around anyway and it does give a lot of flexibility – i.e a single timeline driving many different behaviours mixed and stacked kept in sync.

    Im working on a blog entry which explains all this and hopefully will server as documentation until we get the time to sort the app dev manual more.

  10. alexl says:

    What i want is that the time to go to the final state is always 3 seconds after the last keypress.

    Hmm, i was thinking you could just get the timeline from the actor, rather than keeping around a bunch of behavior objects (or other kinds of non-actor objects). This way the “target” state would be more related to the object its getting set on than some timeline object that isn’t really part of the “physical” model of what is displayed. I dunno if that actually helps make things easier though… I haven’t thought much on this.