Quantcast Animating controls - ESOUI
Thread Tools Display Modes
04/26/14, 02:11 PM   #1
acies
AddOn Author - Click to view addons
Join Date: Apr 2014
Posts: 1
Animating controls

In this tutorial I will show a few examples on how to use the ANIMATION_MANAGER, covering most of the basics.

I'll start off with some of the jargon you'll encounter:
A timeline is a set of animations (not required to be sequential).
Easing is a function applied to the offset for each step in an animation to achieve non-linear transitions. Easing functions are usually made using quadratic or cubic Bezier curves.
Translation refers to the Euclidean transformation of an object's coordinates to a new set of coordinates.

The main types of animations are:
  • ANIMATION_ALPHA
  • ANIMATION_COLOR
  • ANIMATION_SCALE
  • ANIMATION_SCROLL
  • ANIMATION_SIZE
  • ANIMATION_TRANSLATE

The self-explanatory types of directions are:
  • ANIMATION_PLAYBACK_ONE_SHOT (default)
  • ANIMATION_PLAYBACK_LOOP
  • ANIMATION_PLAYBACK_PING_PONG

Let's start with a simple example using CreateSimpleAnimation (single animation):
Lua Code:
  1. function simpleAnimation(control, duration)
  2.     local animation, timeline = CreateSimpleAnimation(ANIMATION_ALPHA, control)
  3.  
  4.     -- start at current alpha
  5.     animation:SetAlphaValues(control:GetAlpha(), 1)
  6.     animation:SetDuration(duration or 1000)
  7.  
  8.     timeline:SetPlaybackType(ANIMATION_PLAYBACK_ONE_SHOT)
  9.     timeline:PlayFromStart()
  10. end

As you will notice, not defining an easing function will simply use linear.
Here's a list of easing functions provided by the API:
  • ZO_BezierInEase
  • ZO_BounceEase
  • ZO_EaseInCubic
  • ZO_EaseInOutCubic
  • ZO_EaseInOutQuadratic
  • ZO_EaseInOutQuartic
  • ZO_EaseInOutQuintic
  • ZO_EaseInQuadratic
  • ZO_EaseInQuartic
  • ZO_EaseInQuintic
  • ZO_EaseOutCubic
  • ZO_EaseOutQuadratic
  • ZO_EaseOutQuartic
  • ZO_EaseOutQuintic
  • ZO_LinearEase (default)
To understand these easing functions, check out http://easings.net/
If you wish to make a custom easing, you can do so with ZO_GenerateCubicBezierEase.
Instead of a tedious trial and error process inputting numbers blindly, I can recommend using this interactive tool to come up with the four numbers required: http://cubic-bezier.com/

Each type of animation has its own method for setting the from and to values.
Here's a more elaborate timeline animation with custom easing:
Lua Code:
  1. -- custom bouncing ("out back") easing
  2. local myEasing = ZO_GenerateCubicBezierEase(.05, 1.85, .75, .75)
  3.  
  4. function timelineAnimation(control)
  5.     local isValidAnchor, point, relativeTo, relativePoint, offsetX, offsetY = control:GetAnchor()
  6.  
  7.     local timeline = ANIMATION_MANAGER:CreateTimeline()
  8.  
  9.     -- scale to 100% using our custom easing
  10.     local popup = timeline:InsertAnimation(ANIMATION_SCALE, control)
  11.     popup:SetScaleValues(0, 1)
  12.     popup:SetDuration(500)
  13.     popup:SetEasingFunction(myEasing)
  14.  
  15.     -- animate opacity from 0% to 100%
  16.     local fadeIn = timeline:InsertAnimation(ANIMATION_ALPHA, control)
  17.     fadeIn:SetAlphaValues(0, 1)
  18.     fadeIn:SetDuration(150)
  19.     fadeIn:SetEasingFunction(ZO_EaseOutQuadratic)
  20.  
  21.     -- begin fading out after 2 seconds
  22.     local fadeOut = timeline:InsertAnimation(ANIMATION_ALPHA, control, 2000)
  23.     fadeOut:SetAlphaValues(1, 0)
  24.     fadeOut:SetDuration(500)
  25.  
  26.     -- begin to slide up after 2 seconds
  27.     local translate = timeline:InsertAnimation(ANIMATION_TRANSLATE, control, 2000)
  28.     translate:SetTranslateOffsets(offsetX, offsetY, offsetX, offsetY - 150)
  29.     translate:SetDuration(500)
  30.     translate:SetEasingFunction(ZO_EaseInQuadratic)
  31.  
  32.  
  33.     -- demonstration of timed callbacks
  34.     timeline:InsertCallback(function()
  35.         d('halfway')
  36.     end, timeline:GetDuration() / 2)
  37.  
  38.     -- reset the control's position once the animation stops
  39.     timeline:SetHandler('OnStop', function()
  40.         d('stopped')
  41.         control:ClearAnchors()
  42.         control:SetAnchor(point, relativeTo, relativePoint, offsetX, offsetY)
  43.     end)
  44.  
  45.     timeline:PlayFromStart()
  46. end

I hope this tutorial clarified some of the less obvious things (cf. http://wiki.esoui.com/Controls)

Last edited by acies : 05/01/14 at 08:07 AM.
  Reply With Quote
04/28/14, 01:08 PM   #2
Sideshow
 
Sideshow's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2014
Posts: 36
Great information! Thanks a lot.
I was wondering, if there is any possibility to alter a timeline animation.
More in detail, I would like to do a translate animation, but the starting coords are not known before the animation is applied to a control. So I would like the animation to take the coords of the control as starting point.
__________________
Author of Combat Cloud
  Reply With Quote
04/28/14, 02:26 PM   #3
GetBackYouPansy
AddOn Author - Click to view addons
Join Date: Apr 2014
Posts: 7
Originally Posted by Sideshow View Post
Great information! Thanks a lot.
I was wondering, if there is any possibility to alter a timeline animation.
More in detail, I would like to do a translate animation, but the starting coords are not known before the animation is applied to a control. So I would like the animation to take the coords of the control as starting point.
You can get each animation out of the timeline and adjust them. There are shortcuts for the first and last animation, see [1], and you can just do all the animations in the timeline like this.

Lua Code:
  1. -- Increase the duration of every animation in the timeline by 250ms
  2. for i = 1, timeline:GetNumAnimations() do
  3.   local anim = timeline:GetAnimation(i)
  4.   anim:SetDuration(anim:GetDuration() + 250)
  5.  -- what you can do ofc depends on the type of animation!
  6. end

One way you might use this is by creating the timeline from virtual (the virtual being defined in UI XML), with some placeholder durations/positions/whatever, then fill in the actual values, and then run it. For an example in the wild, which the simpler example above is based on, see [2] (Lua) and [3] (XML). The base duration from the XML is bumped up by 250ms for every instance of the timeline, several of which are started in parallel.

[1] http://wiki.esoui.com/Controls#AnimationTimeline
[2] https://github.com/PansyLabs/Timers/...s.lua#L207-211
[3] https://github.com/PansyLabs/Timers/...ers.xml#L70-79
__________________
@iyoro ingame | PansyLabs on ESOUI | GitHub (unstable sources for my addons)

Last edited by GetBackYouPansy : 04/28/14 at 02:39 PM. Reason: Failed to put together a coherent post, like, 6 times.
  Reply With Quote
04/29/14, 07:30 AM   #4
Sideshow
 
Sideshow's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2014
Posts: 36
Thanks for the help!
__________________
Author of Combat Cloud
  Reply With Quote
05/14/14, 07:00 PM   #5
Roupine
Join Date: May 2014
Posts: 18
If the starting coordinates aren't known, I've found that simply using SetTranslateDeltas() works great.

ie.
Lua Code:
  1. anim:SetTranslateOffsets(originX, originY, originX-100, originY)
  2. -- Is almost the same as:
  3. anim:SetTranslateDeltas(-100, 0)
SetTranslateDeltas() appears to automatically grab the animated control's current X and Y and sets that as the origin point. What this means is, if the control has moved since the deltas were set it will "snap" back. I get around this by calling SetTranslateDeltas() again just before calling the animation if I'm expecting such a case.

For example, if you want the visual effect of controls "bumping up" each other as new ones come in at the bottom of a stack, you can create an animation to translate the control up, then add an "OnStop" handler that will call SetTranslateDeltas() again so the next time that "bump" is called, it will move up from its new position.

Another thing to keep in mind is that the beziers only affect the animation speed, not the translate coordinates. In order to get a curved animation, you can't simply add two translate animations to the same object -- the latter translation overwrites the former. You have to anchor one object to another object and animate each differently.

For example:
Lua Code:
  1. WINDOW_MANAGER:CreateTopLevelWindow("SomeTLW")
  2. ctExample = WINDOW_MANAGER:CreateControl("AnimEx", SomeTLW, CT_CONTROL)
  3. ctExample.lbl = WINDOW_MANAGER:CreateControl("AnimExLabel", ctExample, CT_LABEL)
  4. -- Set Anchors
  5. ctExample:SetAnchor(CENTER,GuiRoot,CENTER)
  6. ctExample.lbl:SetAnchor(CENTER,ctExample,CENTER)
  7. -- Add content to the controls so they're visible
  8. ctExample.lbl:SetFont("ZoFontWinH2")
  9. ctExample.lbl:SetText("Hello, World!")
  10. SomeTLW:SetHidden(false)
  11.  
  12. ctExample.anim = ANIMATION_MANAGER:CreateTimeline()
  13. -- Add the horizontal slide to the Control:
  14. ctExample.anim.slideX = ctExample.anim:InsertAnimation( ANIMATION_TRANSLATE, ctExample, 0 )
  15. ctExample.anim.slideX:SetDuration(500)
  16. ctExample.anim.slideX:SetEasingFunction(ZO_LinearEase)
  17. ctExample.anim.slideX:SetTranslateDeltas(200,0) -- slide right
  18. -- Add the vertical slide to the Label:
  19. ctExample.anim.slideY = ctExample.anim:InsertAnimation( ANIMATION_TRANSLATE, ctExample.lbl, 0 )
  20. ctExample.anim.slideY:SetDuration(500)
  21. ctExample.anim.slideY:SetEasingFunction(ZO_EaseInCubic)
  22. ctExample.anim.slideY:SetTranslateDeltas(0,-200) -- slide up
  23.  
  24. -- Since the animations are part of the same animation timeline,
  25. -- even though they affect two different objects, you only need to call:
  26. ctExample.anim:PlayFromStart()
I only attached the timeline to the control object (ie. ctExample.anim) because this code is adapted from an ObjectPool factory function. It could be any sort of variable that's convenient.


There might be a better method out there, but... I haven't found it.

Last edited by Roupine : 05/14/14 at 09:49 PM. Reason: added example code
  Reply With Quote
06/09/14, 02:22 PM   #6
Specko
 
Specko's Avatar
AddOn Author - Click to view addons
Join Date: Apr 2014
Posts: 16
First off, thanks for posting this. I am having an issue trying to implement the simple animation. I am using the event for mount status change and the function triggers fine. My issue is with the starting alpha of my label control.

For the below I'm getting attempt to index a nil value for

Code:
--label
    c.label = wm:CreateControl(nil, c, CT_LABEL)
    c.label:SetDimensions(300,200)
	c.label:SetAnchor(CENTER, c, CENTER, 75, -150)
	c.label:SetFont(path .. "|" .. size .. "|" ..  style)
	c.label:SetColor( 128,128,0,.5 )
	c.label:SetHorizontalAlignment( CENTER )
	c.label:SetVerticalAlignment( CENTER )
	c.label:SetText ( "Changed mount status!" )

	return c

  end

  function KillingBlow:simpleAnimation(controlToAnim, duration)
    local animation, timeline = CreateSimpleAnimation(ANIMATION_ALPHA, controlToAnim)

    print("setAlphaValues")
    animation:SetAlphaValues(controlToAnim:GetAlpha(), 1) --Nil value line controlToAnim:GetAlpha()
	print("SetDuration")
    animation:SetDuration(duration or 1000)

    timeline:SetPlaybackType(ANIMATION_PLAYBACK_ONE_SHOT)
    timeline:PlayFromStart()
  end
  Reply With Quote
06/09/14, 03:07 PM   #7
Froali
AddOn Author - Click to view addons
Join Date: Apr 2014
Posts: 13
Hard to tell without more information about controlToAnim. Start debugging with testing if controlToAnim is nil.
If it's not validate it actually has a method named "GetAlpha" (use zgoo AddOn!). Maybe it's not a control or a descendant of control.
  Reply With Quote
06/09/14, 03:46 PM   #8
Specko
 
Specko's Avatar
AddOn Author - Click to view addons
Join Date: Apr 2014
Posts: 16
Originally Posted by Froali View Post
Hard to tell without more information about controlToAnim. Start debugging with testing if controlToAnim is nil.
If it's not validate it actually has a method named "GetAlpha" (use zgoo AddOn!). Maybe it's not a control or a descendant of control.
Thanks I'll use zgoo to test the control.

Last edited by Specko : 06/09/14 at 04:17 PM.
  Reply With Quote
06/09/14, 10:30 PM   #9
Specko
 
Specko's Avatar
AddOn Author - Click to view addons
Join Date: Apr 2014
Posts: 16
It was a scope resolution issue on my part. Doh.
  Reply With Quote
02/23/16, 01:59 AM   #10
@AlphaLemming
 
@AlphaLemming's Avatar
AddOn Author - Click to view addons
Join Date: Apr 2014
Posts: 122
Please make this sticky. I my case it helps much! Thanks.
__________________
Andral Gwain Remus - Ebonheart Pact - EU
Addons: AlphaGear, CraftStore
  Reply With Quote
02/24/16, 04:44 AM   #11
Baertram
 
Baertram's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2014
Posts: 1,618
You could add it to the WIKI so everyone benefits (even outside the forum).
  Reply With Quote

ESOUI » Developer Discussions » Tutorials & Other Helpful Info » Animating controls

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off