Re: Thinking about animation in the Hippo Canvas



On Fri, 2008-05-09 at 13:49 -0400, Havoc Pennington wrote:
> Hi,
> 
> Some observations about the Clutter animation API and aspects you
> might want to improve on -
> 
> * the name "alpha" for the ramp function I thought was pretty bad,
> since alpha means something else... "ramp function" might be good in
> fact.

Yeah, it certainly confused me when I first looked at clutter.

> * animation collision. To give a simple example, say you can expand
> and collapse something. When the user clicks expand you start to
> animate a "width" property. If the animation completes then great, now
> they click "collapse" and you animate width again, down to what it was
> before. However, say the user clicks collapse before your expand
> animation completes. Now you may have two animations at once fighting
> each other. Or if your animation depends on the starting value of a
> property, it may do the wrong thing. Anyway, in general animations
> tend to fight each other (and the rest of the code, for that matter).
> It's just a pain to have your item's state changing around in a
> timeout. It seems like almost all animations have an "inverse" or "go
> back to how it was before" so hand-rolling every time a way to deal
> with this is a pain.

For strict transition animations - like a fade or animated resize - 
I think it's pretty straightforward. You always animate from the current
visible state towards the current programmatic state. 

How easy this is to implement depends on the overall implementation
technique... my thought was to do fades by making a "snapshot" of the
current state of the widget onto an offscreen surface. If you do that,
taking a new snapshot at the current intermediate state is easy.

Not as easy for clutter ... I guess you it would be possible to snapshot
a branch of the scene graph, and then fade between the old and new
contents of that branch, but it's conceptually weird.

For bounces, flashes, and so forth ... category A) in my initial
writeup, it's clearly more problematical, because the two animations
might be changing the same properties of the object. One generic 
technique would be:

 - Stop the first animation
 - Take all property values to their end values for the first animation
 - start a category B) (interpolating) transition 
 - Start the second animation

There is some danger that an excessive use of fades would get tiresome
and look non-physical, but I'm hopeful that in moderation and kept
quick it will just look smooth without being obvious that it is a fade.

To be seen after implementation...

> * a solution I've been using to the collision problem is an idea of a
> "named animation set", where when you start an animation you put it in
> a named set. For example you could put your "expand" and "collapse"
> animations in an "expand-collapse" set. The idea is that sets can have
> some different behaviors; in the expand-collapse example, if you add a
> collapse while expand is running, the expand might be sped up to
> finish almost immediately, and then the collapse would be run after it
> (starting from the known fully-expanded state). Or the expand could be
> canceled immediately. There are also cases where you might want to do
> two things at once (say move and zoom), and in that case the set might
> have a "merge" or "combine" mode. enum { SET_MODE_REPLACE,
> SET_MODE_COMBINE } or something. I have not fully worked this out.
> It's possible sets should be recursive, or maybe animation sets are a
> kind of animation, much like container items are a kind of item.

Interesting. Sounds a bit complex for the programmer :-). My goal for
the HippoCanvas is "make the simple stuff simple, and punt on the hard
stuff"

> * interaction with layout. We just added layout to clutter, and we
> chose to have an extra transform that is only used for painting, not
> for layout. This lets you do something like grow an element slightly
> on mouseover, without pushing everything else on the screen around. Or
> you can have an element "fly" to its slot in a a layout box since the
> layout can be done but the item temporarily painted elsewhere. 

In the 2D case, there is some general utility of having the layout
bounds and the draw bounds of an object be separate ... we hit this when
we were doing fancy theming in GTK+ a couple of years ... wanting a
widget to be able to draw past it's borders. The idea of using that an
item might go past it's layout bounds because there is a separate 
"draw transform" applied when drawing is intriguing, though the possible
effects maybe aren't worth the complexity.

My feeling about animating layout changes was:

- items never move in the layout, they just appear and disappear
  (no flying)
- for appear/disappear we can handle that by interpolating the
  size requisition of parent item.
  (Some complexity in propagation through the hierarchy)
- If in an intermediate state a widget is allocated less than
  its requisition you can either clip the overflow or decide
  by some algorithm which child or children get shortchanged.

> Then idea of "transient" or "display-only" properties used to animate is
> interesting in general I think, but of course it could get unwieldy to
> start having this for every property. But it's nice if the animations
> aren't affecting any properties the "normal" or "logical" code cares
> about.

This is a little related to what I was getting at above with the
difference between the visible state and the programmatic state.

Though obviously if you allow the visible state to deviate in arbitrary
was from the programmatic state, you get more power and more complexity.

> * clutter has some kind of animation convenience API (clutter effects
> I think it's called?) that I don't really understand, though it's
> possible I'm just missing someone explaining it to me.

I thought clutter effects were just canned functions for creating a
behavior hooked up to particular common properties?

Thanks for the input,

- Owen

Attachment: signature.asc
Description: This is a digitally signed message part



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]