Re: How to do animations in 1.16



Hi,

On Tue, Oct 15, 2013 at 10:36:19PM +0200, Alessandro Re wrote:
Hello,

I am trying to get right how animations should be done in Clutter 1.16, but
not everything is clear right now. So, can you help me solve the puzzle?

Apart from the deprecated methods (Actor.animate(), Animator, State) you
have two different APIs for animations, implicit and explicit.
Both ways are documented here:
https://developer.gnome.org/clutter/stable/ClutterActor.html#ClutterActor-animation

BTW, I am using python.
[...]
I miss to understand how I should use Animatable without Animation...
Pheraps is the Transition class that somewhat replaces Animation?
Because, Animatable are used in ClutterTransition and its children, but...

Yes, ClutterTransition uses ClutterAnimatable objects, which is
implemented by ClutterActor.

* ...I fail to understand how ClutterTransition is used.
I can't see where on the documentation it says that Transition is an
abstract class, but in Python when instancing it, it gives me:
TypeError: cannot create instance of abstract (non-instantiable) type
`ClutterTransition'

True again, ClutterTransition is an abstract class. This should be
really mentioned in the docs. Would you mind to open a bug report?

So, I tried subclassing the transition like this:

class PosTrans(clu.Transition):
    def __init__(self):
        super(PosTrans, self).__init__()
    def attached(self, animatable):
        print("Attached to object", animatable)
    def detached(self, animatable):
        print("Detached from object", animatable)
    def compute_value(self, animatable, interval, progress):
        print("Progress", progress)

IMHO you should be able to handle 99% of all situations with
property and keyframe transitions. Apart from some crazy Cogl stuff
(which doesn't work properly with GI anyway), you won't need a
custom one.

and use it like this:

    transition = PosTrans()
    transition.set_from(0)
    transition.set_to(50)
    transition.set_duration(2000)
    transition.set_animatable(actor) # a simple Actor
    transition.start()

But none of the above methods is called (nothing printed).

You have to prefix names of the virtual methods with 'do_'. PyGObject
restriction...

* As a marginal issue, I do not understand why in ClutterAnimatable there
is a get_initial_state, but not a get_final_state, and vice-versa with the
set method. I can't understand how those methods are used.

* So, I tried using PropertyTransition, like this:
    transition = clu.PropertyTransition.new('position')
    transition.set_animatable(actor)
    transition.set_duration(1000)
    transition.set_from(0)
    transition.set_to(100)
    transition.start()

but, again, nothing is happening.

Well, the :position property uses ClutterPoint, but you're setting
integer values... :)

Another common pitfall is the garbage collector, because with
transition.set_animatable() the actor doesn't hold a reference to the
transition. You could either use actor.add_transition() or keep a
reference to the transition yourself.

I do not know where to go from here.
Can someone please help me?

from gi.repository import Clutter

Clutter.init([])

stage = Clutter.Stage()
stage.connect('destroy', lambda stage: Clutter.main_quit())

actor = Clutter.Actor()
bg_color = Clutter.Color.new(255, 0, 0, 255)
actor.set_background_color(bg_color)
actor.set_size(40, 40)
stage.add_child(actor)

# implicit animation, move actor to x=400 in 2s
actor.save_easing_state()
actor.set_easing_duration(2000)
actor.set_x(400)
actor.restore_easing_state()

# explicit animation, move actor to y=400 in 2s
transition = Clutter.PropertyTransition(property_name='y')
transition.set_duration(2000)
transition.set_to(400)
transition.set_animatable(actor)
transition.start()

class FadeToBlackTransition(Clutter.Transition):
    __gtype_name__ = 'FadeToBlackTransition'
    """A pretty usesless custom transition"""

    def __init__(self):
        Clutter.Transition.__init__(self)
        # create a new color interval with black as final color
        stop_color = Clutter.Color.new(0, 0, 0, 255)
        self.interval = Clutter.Interval(value_type=Clutter.Color,
                                         final=stop_color)
        self.set_interval(self.interval)

    def do_attached(self, animatable):
        # XXX: when implementing a GObject virtual method, you
        # have to prefix the method name with 'do_'
        #
        # get the initial color of the actor and use it as the
        # initial value in our interval
        start_color = animatable.get_background_color()
        self.interval.set_initial(start_color)

    def do_compute_value(self, animatable, interval, progress):
        # get the current color from the interval and apply it to
        # the actor
        color = interval.compute(progress)
        animatable.set_background_color(color)

custom_transition = FadeToBlackTransition()
custom_transition.set_duration(2000)
custom_transition.set_animatable(actor)
custom_transition.start()

# when you GC kicks in, your transition will be gone...
#del custom_transition 

stage.show()
Clutter.main()

Thanks for your time!
~Ale

You're welcome

:wq buz

PS: I don't want to sound rude, but would you mind to use 'Clutter'
instead of 'clu' in your tutorial? The former is the usual way for
PyGObject projects, so it would be 'easier' to read for people that are
used to it :)
-- 
GnuPG Fingerprint: 2FFF FC48 C7DF 1EA0 00A0  FD53 8C35 FD2E 6908 7B82

Attachment: signature.asc
Description: Digital signature



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