Page MenuHomePhabricator

Animation framework API for EO
Closed, ResolvedPublic

Description

Original title: refactor elm_transit

elm_transit is a necessary feature that should become easier to use in efl eo API. The idea is that all elm widget should be able to be animated on most eo event (We will need some custom logic for HIDE and DEL). The API would maybe look like :

bool Efl.Ui.Widget.animation_register(EFL_EVENT, AnimationFactory);
Efl.Ui.Animation *Efl.Ui.Widget.animation_exec(EFL_EVENT, Object2Animate); // Will trigger EFL_EVENT_UI_ANIMATION_DONE on the widget when the Efl.Ui.Animation object is deleted at the end of the animation

Efl.Ui.Animation *AnimationFactory.create(Object2Animate);

Efl.Ui.Animation must have at least an efl_del function and that may be pretty much it. All parameter of the animation should be set on the factory. A few default factory should be provided around Evas Map and Evas Filter.

Related Objects

Mentioned In
T5716: Base background object
T5301: Make EFL easier to use by improving its interface
Mentioned Here
D5662: efl_playable: split Efl.Player interface to Efl.Playable interface
rEFL5038223b6152: efl_animation: Add efl_animation
rEFLb4d4e2a2cc4f: efl_animation: Add animation object
rEFL31ed27f00226: efl_animation: Add alpha animation
rEFL58dd0bebaaca: efl_animation: Add alpha animation object
rEFLd4f96f97289e: efl_animation: Add rotate animation
rEFL29917e4e91c6: efl_animation: Add rotate animation object
rEFLc3865609c9a8: efl_animation: Add scale animation
rEFL554052084691: efl_animation: Add scale animation object
rEFLf01c96e54292: efl_animation: Add translate animation
rEFL5a1147d643b6: efl_animation: Add translate animation object
rEFLe1a73fffb9a8: efl_animation: Add group animation
rEFL861a90415c6b: efl_animation: Add group animation object
rEFL923a5b02ebe8: efl_animation: Add parallel group animation and object
rEFL4112a68e321a: efl_animation: Add sequential group animation and object
rEFLa6e03da5f0a9: efl_animation: Support event animation
rEFL87a14507b218: efl_animation: Add pause and resume methods
rEFL108994d383f9: efl_animation: Add repeat_count property
rEFL595f47e202c1: efl_animation: Add start_delay property
rEFLe83facfb37dc: efl_animation: Add repeat_mode property
rEFL39cc542d7f47: efl_animation: Add interpolator property
rEFL6857f349b0b1: efl_animation: Fix shadowing local variable warning
rEFL4dae43e4d13c: efl_animation: Fix to set Efl_Event_Description for event animation
rEFL74155b6e3424: efl_animation: Remove unnecessary macro
rEFL9d1fad8dc163: efl_animation: Remove duration_only_set and total_duration_set methods
rEFLa47ecc87139d: efl_animation: Change protected methods to be internal methods
rEFLc13e2f2be082: docs: fill in missing docs for efl_animation eo class
rEFL2631fabcac93: docs: fill in missing docs for efl_animation_ eo classes
rEFL7bc3ea400c5a: docs: add last missing documentation in efl_animation_object
jpeg added a comment.Apr 5 2017, 10:29 PM

It seems that the Evas Map API will also need some improvement, especially in order to track the geometry of an object. Right now there is a property "move_sync" but this does not handle resizes.
Also, we need the map API to handle relative coordinates, eg:

obj.map_rotate(MAP_RELATIVE_TO_OBJECT, 0.5, 0.5, 45.0);

This would rotate the object by 45 degrees based on center point relative to itself. So, invariant to object size & position.
I believe Edje already handles some of those features.

@jpeg Thank you for your opinions.

Yes, there is no property "sync" for resize. (By default, sync is always done for resize.) I will add it after refactorying animation.
Regarding relative coordinates for animation, I will support it on refactorying animation.

I think we should provide Efl.Canvas.Object.animation_register( ) instead of Efl.Ui.Widget.animation_register( ).
Because Efl.Canvas.Object supports animation with using position change and evas_map. (e.g. evas_object_box, evas_object_rectangle, etc.)

I think we should provide Efl.Canvas.Object.animation_register( ) instead of Efl.Ui.Widget.animation_register( ).
Because Efl.Canvas.Object supports animation with using position change and evas_map. (e.g. evas_object_box, evas_object_rectangle, etc.)

To provide above, I think that evas_object_animation_ or evas_object_transit_ APIs should be created and supported instead of elm_transit_ APIs.

jpeg added a comment.Apr 5 2017, 11:30 PM

Yes. Forget entirely about elm_transit. I think we want a fresh animation framework.

The thing that you may actually want to get some inspiration from would be efx: https://git.enlightenment.org/devs/discomfitor/efx.git/ . If you want to reuse some of the code, please let me know as we can maybe merge first efx in efl tree.

I'd like to see two things here:

  • ways to combine multiple independent animations. More common than not, applications that do animations will do "X after animations A and B are finished", where X can be go to the next stage, or start yet another animation. Things like "A is slide right" while "B is fade out", which can vary on time (ie: depends on screen position, thus larger screens may take more time)... A generic way to wait on multiple "done", like proposed for Promise/Future is very helpful...
  • visual designer... like in flash, be able to define it graphically by manually position, move to next frame, adjust and have the code to generate the interpolation. It's usually a big fight with designers, where they are used to flash and visual tools... then they provide that to you and you need to figure out yourself when things change, how they change... it's rare for them to go review what they did and generate a textual timeline "0.1s - move obj A +10,+10, fade obj B 20%; 0.5s obj A is at WxH". Us being able to manually type these things in C is only good for our own development/testing, not that useful to deal with designers or for ourselves to create something appealing.

I think we can easily provide a composite animation by having a factory that take other animation factory as parameters. As for the second point, I would guess that the solution would be to provide a file to the composite animation factory as potential input to, but that one is clearly out of scope at this point.

@cedric
Thanks about gfx. I wil look into it.
Regarding factory, do you mean efl_ui_factory with using Efl.Model?
Or do you mean just a class which contains animation properties?

@barbieri

jpeg renamed this task from Refactor elm_transit to Animation framework API for EO.Apr 10 2017, 9:29 PM
jpeg updated the task description. (Show Details)
jpeg added a comment.Apr 10 2017, 9:39 PM

I believe that we want an EO API first, but the end goal is definitely to be able to provide an easy-to-use GUI for defining animations. The storage format would then be json/xml/eet/lua/whatever and that "animation script" could then either be executed at runtime or be transpiled to C (long term vision). This means that an animation needs to be definable in a descriptive manner (not imperative).

Qt's animations framework is incredibly simple and provides those transitions and bundling of animations.

One thing we need to keep in mind though, is that we will need both Evas_Map and geometry property-based animations. It is not the same to zoom an object (with map) and scale it (with geometry_set).

I am working on devs/jaehyun/animation branch of efl git. (https://git.enlightenment.org/core/efl.git/log/?h=devs/jaehyun/animation)

For now, I designed class as follows.

Efl.Object <--- Efl.Animation <---Efl.Object_Animation <--- Efl.Alpha_Animation / Efl.Rotate_Animation / Efl.Scale_Animation / Efl.Translate_Animation

Later, I am going to add Efl.Animation_Group class as follows.

Efl.Object <--- Efl.Animation <--- Efl.Animation_Group

Also I am going to add methods in Efl.Canvas.Object to register Efl.Animation and execute Efl.Animation something like cedric described in the task description.

Please let me know if you have any comment or if you think there is something wrong in this design. Especially about class hierarchy or interfaces.

Shouldn't all this live under the Efl.Gfx namespace?
or we have plans to support some kind of non-graphical animation/interpolation?

And why you write the base Efl.Animation class? can an animation run without an object?

@DaveMDS

I designed Efl.Animation as abstract class to support group animation (e.g. Efl.Group_Animation).
If abstract class Efl.Animation does not exist, then it would be hard to support grouping animations. (i.e. providing common animation interfaces to all animation classes)
I referred other UI frameworks and they also provide similar class hierarchies. Animator abstract class with AnimatorSet class in Android and QAbstractAnimation abstract class with QAnimationGroup class in Qt.

I think that it is not necessary to assign object to animation (i.e. Efl.Animation).
I think that Efl.Animation only provides the current value based on the given start value, end value and interpolation function without assigning object to the animation.
This kind of class design is found in Android (ValueAnimator class) and Qt (QVariantAnimation class) as well.

jpeg added a comment.May 10 2017, 3:53 AM

All the above class names need to be in the same namespace. ie. more:

  • Efl.Animation
    • Efl.Animation.Group
    • Efl.Animation.Object
      • Efl.Animation.Alpha
      • Efl.Animation.Scale
      • etc...

It could also be done inside Efl.Gfx, like Efl.Gfx.Animation or Efl.Gfx.Anim.

jpeg added a comment.May 10 2017, 3:54 AM

This kind of class design is found in Android (ValueAnimator class) and Qt (QVariantAnimation class) as well.

Remember that we don't have a meta property model like those frameworks. ie. we have no way to bind a pair (name,value) to a property function call. At least for now.

Jaehyun_Cho added a subscriber: singh.amitesh.EditedMay 26 2017, 1:13 AM

The following was discussed with @cedric, @jpeg, @singh.amitesh, @woohyun.

Animation Factory class is going to be used instead of Animation class.
For developers, Animation Instance class will be also provided.

//example code
Efl_Animation_Factory *f = efl_add(EFL_ANIMATION_FACTORY_CLASS, NULL);
efl_animation_factory_alpha_set(f, 0.5, 1.0);
...
Efl_Animation_Instance *ai = efl_animation_factory_create(f, target);

Based on the above factory and instance class, each instance of Animation Instance class contains only one target object.

Therefore, animating more than one object at the same time is not supported by event animation automatically. (It should be done manually in event callback function.)

The events of animation, "start", "animate", "end", are not recommended but they should be supported.

jpeg added a comment.EditedMay 28 2017, 9:37 PM

I believe Efl.Animation is good enough a name, instead of Efl.Animation.Factory. Or Efl.Ui.Animation.

Extra: I was thinking about another kind of animation, which is not time based, but instead position-based. It's not an animation per se but still a visual effect. Example: scroll up a list and a newly visible item's alpha depends on how much of the item is visible. I think we should keep this kind of transition in mind but this may fall outside the scope of this ticket.

+1 for the remove of "Factory" from the name

Based on the factory method pattern here, the animation factory should contain more than one animation effects.
And each animation effect can be same type (e.g. Rotation effect with different pivot point).
Moreover, each animation effect should have its own animation properties such as "duration".

To apply the above feature, I think the following classes are required.

  1. Efl.Animation.Effect (for effect property)
  2. Efl.Animation (for factory)
  3. Efl.Animation.Instance (for instance)

The example is as follows.

//Create animation factory
Efl.Animation *factory = efl_add(EFL_ANIMATION_CLASS, NULL);

//Create animation effect
Efl.Animation.Effect *effect = efl_animation_effect_add(factory);

//Set animation effect's properties
efl_animation_effect_duration_set(effect, duration);
efl_animation_effect_alpha_set(effect, from_alpha, to_alpha);
...

//Create animation instance
Efl.Animation.Instance *instance = efl_animation_instance_create(factory);

/* App can either runs animation manually (Case1) OR registers animation to an event (Case2) */
//Case 1 : Run animation instance manually
efl_animation_instance_start(instance);

//Case 2 : Register animation factory to an event (animation automatically runs when the event happens)
efl_canvas_object_event_animation_set(object, EFL_ANIMATION_EVENT_TYPE_SHOW, factory);

In the above case, I doubt if it is convenient to application developers. Because we requires application developers to know Efl.Animation.Effect class as well.

Is there any idea or thought about this?

jpeg added a comment.May 29 2017, 11:42 PM

Hmm I thought it would look like this:

// this is our "factory"
Efl_Animation *anim = efl_add(EFL_ANIMATION_PARALLEL, NULL);

// create alpha and rotation effects
Efl_Animation *a1 = efl_add(EFL_ANIMATION_ALPHA, anim, efl_animation_alpha_set(efl_added, 0.0, 1.0), efl_animation_duration_set(efl_added, 1.0));
Efl_Animation *a2 = efl_add(EFL_ANIMATION_ROTATE, anim, efl_animation_rotation_set(efl_added, 0.0, 90.0), efl_animation_duration_set(efl_added, 1.0));

// add them to their parent group. maybe this is not needed since the parent was already set above
efl_animation_parallel_add(anim, a1);
efl_animation_parallel_add(anim, a2);

// run explicitely on object obj
Efl_Animation_Instance *inst = efl_animation_start(anim, obj); // could be obj, anim depending on where the API is implemented
// inst can be ignored. it will die automatically

In this example we could have either one "Effect" super class or multiple classes like Alpha, Rotation, etc... Like you proposed at first.
The duration could also be set on the group instead of on each individual child effect (then they would all have the same duration).

Now, in case there is only one effect:

Efl_Animation *a1 = efl_add(EFL_ANIMATION_ALPHA, NULL, efl_animation_alpha_set(efl_added, 0.0, 1.0), efl_animation_duration_set(efl_added, 1.0));
efl_animation_start(a1, obj);

The animation class "Alpha" is also a factory.

@jpeg,

I haven't thought about "Group Factory" before.

Then I guess each factory represents only one effect and a group factory contains other factories.

I think your idea is way better~ Thank you! :)

jpeg added a comment.Jun 14 2017, 6:53 PM

As discussed with @Jaehyun_Cho yesterday, we have some issues if an animation is meant to end with a mapped state, and the object should remain mapped. As in that case the next animation should likely start from this original mapped state, and thus add more gfx_map operations on top of those already existing. While we can easily find a way to save & restore the state of a mapped object (by saving for instance just the number of operations applied in the map), I'm afraid this could balloon out if a couple of animations cycle and start from the mapped state of the previous one. This could also be left to the responsibility of the user to make sure that animations start from a clean state. Or animations need to be incredibly simple so that we can read back the values of rotation, zoom, translation, etc...

@jpeg, what if we expose both termination states and link animations using these explicitly...

if I read you right, in one case you want a rotation to 90deg then fade would fade the rotated map.... while in another there is a rotation, reset to initial state (0deg), then fade... so it would be something like:

rotate(90).then(fade(10%))

x

rotate(90).then(reset()).then(fade(10%))
jpeg added a comment.Jun 14 2017, 8:18 PM

@barbieri you got the idea. And yes this is probably what we need. But animations are more generic than just "rotate" since even for rotate there's a rotation center around a pivot object, etc...
So I'm not entirely sure how to do that nicely.

Also, I'm not talking about chained animations, which we are planning to handle. But I'm talking about the case were there was one animation, then the final state was maintained (eg. rotated 90) and a later animation needs to bring the object to another state (eg. rotated 0).

In fact this example shows that the 2nd animation is based on a new state change rather than applying more operations. Hmm...

cedric raised the priority of this task from TODO to High.Jul 10 2017, 3:16 PM
jpeg added a comment.Dec 11 2017, 6:50 PM

7bc3ea400c docs: add last missing documentation in efl_animation_object
2631fabcac docs: fill in missing docs for efl_animation_ eo classes
c13e2f2be0 docs: fill in missing docs for efl_animation eo class
a47ecc8713 efl_animation: Change protected methods to be internal methods
9d1fad8dc1 efl_animation: Remove duration_only_set and total_duration_set methods
74155b6e34 efl_animation: Remove unnecessary macro
4dae43e4d1 efl_animation: Fix to set Efl_Event_Description for event animation
6857f349b0 efl_animation: Fix shadowing local variable warning
39cc542d7f efl_animation: Add interpolator property
e83facfb37 efl_animation: Add repeat_mode property
595f47e202 efl_animation: Add start_delay property
108994d383 efl_animation: Add repeat_count property
87a14507b2 efl_animation: Add pause and resume methods
a6e03da5f0 efl_animation: Support event animation
4112a68e32 efl_animation: Add sequential group animation and object
923a5b02eb efl_animation: Add parallel group animation and object
861a90415c efl_animation: Add group animation object
e1a73fffb9 efl_animation: Add group animation
5a1147d643 efl_animation: Add translate animation object
f01c96e542 efl_animation: Add translate animation
5540520846 efl_animation: Add scale animation object
c3865609c9 efl_animation: Add scale animation
29917e4e91 efl_animation: Add rotate animation object
d4f96f9728 efl_animation: Add rotate animation
58dd0bebaa efl_animation: Add alpha animation object
31ed27f002 efl_animation: Add alpha animation
b4d4e2a2cc efl_animation: Add animation object
5038223b61 efl_animation: Add efl_animation

jpeg added a comment.Dec 11 2017, 6:53 PM

@Jaehyun_Cho we talked about one last missing feature in animations, I think:
Animations can keep the final state, but what's missing is keep the initial state. This requires two things:

  1. Split from & to values into two properties. Or have another way to say "ignore from"
  2. Be able to guess current state and interpolate from that

@jpeg
I understand and agree with your point.
But I concern about one thing. If efl_gfx_map is manually applied to an object which was animated by Efl_Animation, then efl_gfx_map would not start from the last state of Efl_Animation.
Is it ok?

jpeg added a comment.Dec 12 2017, 9:04 PM

Yeah I think it's OK. Mixing manual and automatic calls to map doesn't sound like a great idea :)

zmike edited projects, added Restricted Project; removed efl.Jun 11 2018, 6:54 AM
zmike edited projects, added efl; removed Restricted Project.Jun 11 2018, 8:57 AM
bu5hm4n edited projects, added efl: main loop; removed efl.Jun 11 2018, 10:42 AM
bu5hm4n added subscribers: Jaehyun, bu5hm4n.

@Jaehyun is that resolved now?

Jaehyun_Cho closed this task as Resolved.Jun 13 2018, 9:46 PM

@bu5hm4n

Thanks for letting me know.
This has been resolved. (you may check Efl.Canvas.Animation class)