update to resolve some performance issues ( pooling animations )

Sammy James [03-25-14 - 05:34]
update to resolve some performance issues ( pooling animations )
Filename
PSBT.txt
core/PSBT.lua
core/PSBT_Fifo.lua
core/PSBT_Label.lua
core/PSBT_ScrollArea.lua
helpers/PSBT_AnimationPool.lua
helpers/PSBT_Fade.lua
helpers/PSBT_Parabola.lua
libs/LibAnimation-1.0/LibAnimation.lua
diff --git a/PSBT.txt b/PSBT.txt
index ae6ad1b..519c1bd 100644
--- a/PSBT.txt
+++ b/PSBT.txt
@@ -16,7 +16,9 @@ core/PSBT_Media.lua
 core/PSBT_Constants.lua

 ## helpers
+helpers/PSBT_AnimationPool.lua
 helpers/PSBT_Parabola.lua
+helpers/PSBT_Fade.lua

 ## core modules
 core/PSBT_Module.lua
@@ -32,7 +34,6 @@ modules/PSBT_LowSomething.lua
 modules/PSBT_Ultimate.lua

 ## core
-core/PSBT_Fifo.lua
 core/PSBT_Label.lua
 core/PSBT_ScrollArea.lua
 core/PSBT.lua
diff --git a/core/PSBT.lua b/core/PSBT.lua
index 3defc25..a17542b 100644
--- a/core/PSBT.lua
+++ b/core/PSBT.lua
@@ -34,6 +34,10 @@ local PSBT = ZO_ObjectPool:Subclass()
 PSBT._modules  = {}
 PSBT._areas    = {}
 PSBT._events   = {}
+PSBT.__DEBUG_UPDATE = 0
+PSBT.__DEBUG = false
+
+local PSBT_Fade         = PSBT_Fade

 local CBM               = CALLBACK_MANAGER
 local PSBT_ScrollArea   = PSBT_ScrollArea
@@ -76,16 +80,31 @@ function PSBT:OnLoaded( addon )
     print( 'Loading PSBT' )
     CBM:FireCallbacks( PSBT_EVENTS.LOADED, self )

-    self._areas[ PSBT_AREAS.INCOMING ]     = PSBT_ScrollArea:New( self.control, PSBT_AREAS.INCOMING,     self:GetSetting( PSBT_AREAS.INCOMING ) )
-    self._areas[ PSBT_AREAS.OUTGOING ]     = PSBT_ScrollArea:New( self.control, PSBT_AREAS.OUTGOING,     self:GetSetting( PSBT_AREAS.OUTGOING ) )
-    self._areas[ PSBT_AREAS.STATIC ]       = PSBT_ScrollArea:New( self.control, PSBT_AREAS.STATIC,       self:GetSetting( PSBT_AREAS.STATIC ) )
-    self._areas[ PSBT_AREAS.NOTIFICATION ] = PSBT_ScrollArea:New( self.control, PSBT_AREAS.NOTIFICATION, self:GetSetting( PSBT_AREAS.NOTIFICATION ) )
+    self._fadeIn    = PSBT_Fade:New( 1.0, 0.0 )
+    self._fadeOut   = PSBT_Fade:New( 0.0, 1,0 )
+
+    self._areas[ PSBT_AREAS.INCOMING ]     = PSBT_ScrollArea:New( self.control, PSBT_AREAS.INCOMING,     self:GetSetting( PSBT_AREAS.INCOMING ), self._fadeIn, self._fadeOut )
+    self._areas[ PSBT_AREAS.OUTGOING ]     = PSBT_ScrollArea:New( self.control, PSBT_AREAS.OUTGOING,     self:GetSetting( PSBT_AREAS.OUTGOING ), self._fadeIn, self._fadeOut )
+    self._areas[ PSBT_AREAS.STATIC ]       = PSBT_ScrollArea:New( self.control, PSBT_AREAS.STATIC,       self:GetSetting( PSBT_AREAS.STATIC ), self._fadeIn, self._fadeOut )
+    self._areas[ PSBT_AREAS.NOTIFICATION ] = PSBT_ScrollArea:New( self.control, PSBT_AREAS.NOTIFICATION, self:GetSetting( PSBT_AREAS.NOTIFICATION ), self._fadeIn, self._fadeOut )

     CBM:RegisterCallback( PSBT_EVENTS.CONFIG, function( ... ) self:SetConfigurationMode( ... ) end )
     self.control:SetHandler( 'OnUpdate', function( _, frameTime ) self:OnUpdate( frameTime ) end )
 end

 function PSBT:OnUpdate( frameTime )
+    if ( self.__DEBUG ) then
+        if ( frameTime - self.__DEBUG_UPDATE > 2 ) then
+            self.__DEBUG_UPDATE = frameTime
+            d( '-------------- PSBT_DEBUG_UPDATE --------------')
+            d( 'LABELS total = ' .. self:GetTotalObjectCount() .. ', active = ' .. self:GetActiveObjectCount() .. ', inactive = ' .. self:GetFreeObjectCount() )
+            d( 'FADEIN total = ' .. self._fadeIn:GetTotalObjectCount() .. ', active = ' .. self._fadeIn:GetActiveObjectCount() .. ', inactive = ' .. self._fadeIn:GetFreeObjectCount() )
+            d( 'FADEOUT total = ' .. self._fadeOut:GetTotalObjectCount() .. ', active = ' .. self._fadeOut:GetActiveObjectCount() .. ', inactive = ' .. self._fadeOut:GetFreeObjectCount() )
+            d( 'INCOMING PARABOLAS total = ' .. self._areas[ PSBT_AREAS.INCOMING ]._parabola:GetTotalObjectCount() )
+            d( 'OUTGOING PARABOLAS total = ' .. self._areas[ PSBT_AREAS.OUTGOING ]._parabola:GetTotalObjectCount() )
+        end
+    end
+
     for k,label in pairs( self:GetActiveObjects() ) do
         if ( label:IsExpired( frameTime ) ) then
             self:ReleaseObject( k )
@@ -228,4 +247,6 @@ end
 -- LEAVE ME THE FUARK ALONE
 function Initialized( control )
     _G.PSBT = PSBT:New( control )
+
+    SLASH_COMMANDS['/psbtdebug'] = function() _G.PSBT.__DEBUG = not _G.PSBT.__DEBUG end
 end
diff --git a/core/PSBT_Fifo.lua b/core/PSBT_Fifo.lua
deleted file mode 100644
index 702e7a9..0000000
--- a/core/PSBT_Fifo.lua
+++ /dev/null
@@ -1,87 +0,0 @@
-------
--- First in First Out container
--- reference:
--- https://github.com/daurnimator/lomp2/blob/master/fifo.lua
-------
-
-local select , setmetatable = select , setmetatable
-
-PSBT_Fifo = {}
-local mt =
-{
-    __index = PSBT_Fifo,
-    __newindex = function( f, k, v )
-        if ( type( k ) == 'number' ) then
-            return rawset( f, k, v )
-        end
-    end,
-}
-
-function PSBT_Fifo.New( ... )
-    return setmetatable( { head = 1, tail = select( '#', ... ), ... }, mt )
-end
-
-function PSBT_Fifo:Size()
-    return self.tail - self.head + 1
-end
-
-function PSBT_Fifo:Peek()
-    return self[ self.head ]
-end
-
-function PSBT_Fifo:Push( value )
-    self.tail = self.tail + 1
-    self[ self.tail ] = value
-end
-
-function PSBT_Fifo:Pop()
-    local head, tail = self.head, self.tail
-    if ( head > tail ) then
-        return nil
-    end
-
-    local value = self[ head ]
-    self[ head ] = nil
-    self.head = head + 1
-    return value
-end
-
-function PSBT_Fifo:Remove( index )
-    local head, tail = self.head, self.tail
-
-    if head + index > tail then
-        return
-    end
-
-    local position  = head + index - 1
-    local value     = self[ position ]
-
-    if ( position <= (head + tail) * 0.5 ) then
-        for i = position, head, -1 do
-            self[ i ] = self[ i - 1 ]
-        end
-        self.head = head + 1
-    else
-        for i = position, tail do
-            self[ i ] = self[ i + 1 ]
-        end
-        self.tail = tail - 1
-    end
-
-    return value
-end
-
-local iterator = function( fifo, previous )
-    local i = fifo.head + previous
-    if ( i > fifo.tail ) then
-        return nil
-    end
-
-    return previous + 1, fifo[ i ]
-end
-
-function PSBT_Fifo:Iterator()
-    return iterator, self, 0
-end
-
-mt.__len = PSBT_Fifo.Size
\ No newline at end of file
diff --git a/core/PSBT_Label.lua b/core/PSBT_Label.lua
index 3e4fea0..f76e47e 100644
--- a/core/PSBT_Label.lua
+++ b/core/PSBT_Label.lua
@@ -19,8 +19,6 @@ function PSBT_Label:Initialize( objectPool )
     self.moving  = false
     self.direction = PSBT_SCROLL_DIRECTIONS.UP
     self.iconPos = PSBT_ICON_SIDE.LEFT
-
-    self.control:SetAlpha( 0.0 )
 end

 function PSBT_Label:SetMoving( set )
@@ -61,6 +59,7 @@ function PSBT_Label:Finalize()
     self:SetExpire( 0 )
     self:SetMoving( false )
     self.control:ClearAnchors()
+    self.control:SetScale( 1.0 )
 end

 function PSBT_Label:SetText( text )
diff --git a/core/PSBT_ScrollArea.lua b/core/PSBT_ScrollArea.lua
index d1ad9bf..e87efe9 100644
--- a/core/PSBT_ScrollArea.lua
+++ b/core/PSBT_ScrollArea.lua
@@ -1,19 +1,15 @@
-local LibAnim = LibStub( 'LibAnimation-1.0' )
-if ( not LibAnim ) then return end
-
 PSBT_ScrollArea     = ZO_Object:Subclass()
+
 local CBM           = CALLBACK_MANAGER
 local tinsert       = table.insert
 local tremove       = table.remove
 local NUM_STICKY    = 4
-
-local PSBT_Fifo     = PSBT_Fifo
 local CENTER        = CENTER
 local BOTTOM        = BOTTOM
 local TOP           = TOP
-
 local PSBT_EVENTS   = PSBT_EVENTS
 local PSBT_SCROLL_DIRECTIONS = PSBT_SCROLL_DIRECTIONS
+local PSBT_Parabola = PSBT_Parabola

 function PSBT_ScrollArea:New( ... )
     local result = ZO_Object.New( self )
@@ -21,61 +17,37 @@ function PSBT_ScrollArea:New( ... )
     return result
 end

-function PSBT_ScrollArea:Initialize( super, areaName, settings )
+function PSBT_ScrollArea:Initialize( super, areaName, settings, fadeIn, fadeOut )
     self.name           = areaName
     self.control        = super:GetNamedChild( areaName )
     self.background     = self.control:GetNamedChild( '_BG' )
     self.label          = self.control:GetNamedChild( '_Name' )
     self._newSticky     = false
     self._height        = self.control:GetHeight()
-    self._sticky        = PSBT_Fifo.New()
-    self._pendingSticky = PSBT_Fifo.New()
+    self._sticky        = {}
+    self._pendingSticky = {}
     self._normal        = {}
-    self._pendingNormal = PSBT_Fifo.New()
-    self._direction     = settings.dir
-    self._iconSide      = settings.icon
-
-    self._parabolaPoints = PSBT_Parabola:Calculate( self.control:GetHeight(), settings.arc, 50, self._direction )
+    self._pendingNormal = {}
+    self._fadeIn        = fadeIn
+    self._fadeOut       = fadeOut

-    self:Position( settings )
+    self:SetSettings( settings )
     self:SetConfigurationMode( false )
     self.control:SetHandler( 'OnUpdate', function( event, ... ) self:OnUpdate( ... ) end )

     CBM:RegisterCallback( PSBT_EVENTS.CONFIG, function( ... ) self:SetConfigurationMode( ... ) end )
 end

-function PSBT_ScrollArea:InitParabolaAnim( control )
-    local anim = LibAnim:New( control )
-
-    local points = self._parabolaPoints
-    local x, y = points[1].x, points[1].y
-    local point = nil
-
-    local duration = 3000 / #points
-
-    for i=1,#points do
-        point = points[ i ]
-        anim:TranslateToFrom( x, y, point.x, point.y, duration, (i - 1) * duration )
-
-        x = point.x
-        y = point.y
-    end
-
-    return anim
-end
-
 function PSBT_ScrollArea:SetConfigurationMode( enable )
     self.control:SetMovable( enable )
     self.control:SetMouseEnabled( enable )
     self.label:SetHidden( not enable )
     if ( enable ) then
-        local enter = LibAnim:New( self.background )
-        enter:AlphaTo( 1.0, 500 )
-        enter:Play()
+        local anim = self._fadeIn:Apply( self.background )
+        anim:Play()
     else
-        local exit = LibAnim:New( self.background )
-        exit:AlphaTo( 0.0, 500 )
-        exit:Play()
+        local anim = self._fadeOut:Apply( self.background )
+        anim:Play()
     end
 end

@@ -103,126 +75,105 @@ function PSBT_ScrollArea:Push( entry, sticky )
     entry:SetIconPosition( self._iconSide )

     if ( sticky ) then
-        self._pendingSticky:Push( entry )
+        tinsert( self._pendingSticky, entry )
     else
-        self._pendingNormal:Push( entry )
+        tinsert( self._pendingNormal, entry )
     end
 end

 function PSBT_ScrollArea:SetSettings( settings )
-    self._iconSide = settings.icon
-    self._direction = settings.dir
-    self._parabolaPoints = PSBT_Parabola:Calculate( self.control:GetHeight(), settings.arc, 50, self._direction )
+    self._iconSide       = settings.icon
+    self._direction      = settings.dir
+    self._parabola       = PSBT_Parabola:New( self.control:GetHeight(), settings.arc, 50, self._direction )
+    self:Position( settings )
 end

 function PSBT_ScrollArea:OnUpdate( frameTime )
-    if ( not self._sticky:Size() and
+    if ( not #self._sticky and
          not #self._normal and
-         not self._pendingNormal:Size() and
-         not self._pendingSticky:Size() ) then
+         not #self._pendingNormal and
+         not #self._pendingSticky ) then
         return
     end

-    while ( self._sticky:Size() > NUM_STICKY ) do
-        local old = self._sticky:Pop()
-        local anim = LibAnim:New( old.control )
-        anim:AlphaTo( 0.0, 200 )
-        anim:Play()
-
+    while ( #self._sticky > NUM_STICKY ) do
+        local old = tremove( self._sticky, 1 )
         old:SetMoving( false )

         old:SetExpire( frameTime + 2 )
         self._newSticky = true
     end

-    repeat
-        local entry = self._sticky:Peek()
-        if ( entry and entry:WillExpire( frameTime + 2 ) ) then
-            local anim = LibAnim:New( entry.control )
-            anim:AlphaTo( 0.0, 200 )
-
-            local ypos = 0
-            if ( self._direction == PSBT_SCROLL_DIRECTIONS.UP ) then
-                ypos = -100
-            elseif ( self._direction == PSBT_SCROLL_DIRECTIONS.DOWN ) then
-                ypos = 100
-            end
-
-            anim:TranslateTo( 0, ypos, 200 )
-            anim:ScaleTo( 0.5, 200 )
-            anim:Play()
-
-            entry:SetMoving( false )
-
-            self._sticky:Pop()
-            self._newSticky = true
-        end
-    until( not entry or not entry:WillExpire( frameTime + 2 )  )
-
-    if ( self._pendingNormal:Size() ) then
-        local newEntry = self._pendingNormal:Pop()
+    if ( #self._pendingNormal ) then
+        local newEntry = tremove( self._pendingNormal, 1 )
         if ( newEntry ) then
-            newEntry:SetExpire( frameTime + 5 )
-            local anim = LibAnim:New( newEntry.control )
-            anim:AlphaTo( 1.0, 200 )
+            newEntry:SetExpire( frameTime + 3 )
+
+            local anim = self._fadeIn:Apply( newEntry.control )
             anim:Play()

             tinsert( self._normal, newEntry )
         end
     end

-    if ( self._pendingSticky:Size() ) then
-        local newEntry = self._pendingSticky:Pop()
+    if ( #self._pendingSticky ) then
+        local newEntry = tremove( self._pendingSticky, 1 )
         if ( newEntry ) then
             newEntry:SetExpire( frameTime + 5 )

-            newEntry.control:SetScale( 0.5 )
-
-            local anim = LibAnim:New( newEntry.control )
-            anim:AlphaTo( 1.0, 200 )
-            anim:ScaleTo( 1.0, 200 )
+            local anim = self._fadeIn:Apply( newEntry.control )
             anim:Play()

-            self._sticky:Push( newEntry )
+            tinsert( self._sticky, newEntry )
             self._newSticky = true
         end
     end

     local i = 1
+    local entry = nil
+
     while ( i <= #self._normal ) do
-        local entry = self._normal[ i ]
+        entry = self._normal[ i ]

-        if ( entry:WillExpire( frameTime + 2 ) ) then
-            local anim = LibAnim:New( entry.control )
-            anim:AlphaTo( 0.0, 200, nil, nil, ZO_EaseInOutQuadratic )
+        if ( entry:WillExpire( frameTime + 0.5 ) ) then
+            local anim = self._fadeOut:Apply( entry.control )
             anim:Play()

             entry:SetMoving( false )
-
             tremove( self._normal, i )
         else
             if ( not entry:IsMoving() ) then
-                local anim = self:InitParabolaAnim( entry.control )
-                anim:ScaleTo( 1.25, 1500 )
-                anim:ScaleToFrom( 1.25, 1.0, 1500, 1500 )
+                local anim = self._parabola:Apply( entry.control )
                 anim:Play()
-
                 entry:SetMoving( true )
             end
             i = i + 1
         end
     end

-    local top = 0
-    for i, entry in self._sticky:Iterator() do
-        if ( self._newSticky ) then
-            local anim = LibAnim:New( entry.control )
-            anim:TranslateTo( 0, top, 200 )
-            anim:Play()
+
+    i = 1
+    local top = 0

-            entry:SetMoving( true )
+    while ( i <= #self._sticky ) do
+        entry = self._sticky[ i ]
+        if ( entry:WillExpire( frameTime + 0.5 ) ) then
+            local anim = self._fadeOut:Apply( entry.control )
+            anim:Play()

-            top = top + entry:GetHeight()
+            tremove( self._sticky, i )
+            self._newSticky = true
+        else
+            if ( self._newSticky ) then
+                entry.control:SetAnchor( CENTER, self.control, CENTER, 0, top )
+
+                if ( self._direction == PSBT_SCROLL_DIRECTIONS.UP ) then
+                    top = top - entry:GetHeight()
+                else
+                    top = top + entry:GetHeight()
+                end
+            end
+            i = i + 1
         end
     end

diff --git a/helpers/PSBT_AnimationPool.lua b/helpers/PSBT_AnimationPool.lua
new file mode 100644
index 0000000..27860ab
--- /dev/null
+++ b/helpers/PSBT_AnimationPool.lua
@@ -0,0 +1,28 @@
+local ZO_ObjectPool = ZO_ObjectPool
+local LibAnim = LibStub( 'LibAnimation-1.0' )
+
+PSBT_AnimationPool = ZO_ObjectPool:Subclass()
+
+function PSBT_AnimationPool:New( create, reset )
+    return ZO_ObjectPool.New( self, self.Create, function( ... ) self:Reset( ... ) end )
+end
+
+function PSBT_AnimationPool:Create()
+    return LibAnim:New()
+end
+
+function PSBT_AnimationPool:Reset( animation )
+    animation:Stop()
+end
+
+function PSBT_AnimationPool:Apply( control )
+    local anim, key = self:AcquireObject()
+    anim:SetUserData( key )
+    anim:Apply( control )
+    anim:SetHandler( 'OnStop',
+        function( animation )
+            self:ReleaseObject( anim:GetUserData() )
+        end )
+
+    return anim
+end
\ No newline at end of file
diff --git a/helpers/PSBT_Fade.lua b/helpers/PSBT_Fade.lua
new file mode 100644
index 0000000..b4cc9d6
--- /dev/null
+++ b/helpers/PSBT_Fade.lua
@@ -0,0 +1,19 @@
+local PSBT_AnimationPool = PSBT_AnimationPool
+PSBT_Fade = PSBT_AnimationPool:Subclass()
+
+function PSBT_Fade:New( to, from )
+    local result = PSBT_AnimationPool.New( self )
+    result:Initialize( to, from )
+    return result
+end
+
+function PSBT_Fade:Initialize( to, from )
+    self._target    = to
+    self._from      = from
+end
+
+function PSBT_Fade:Create()
+    local anim = PSBT_AnimationPool.Create( self )
+    anim:AlphaToFrom( self._from, self._target, 200 )
+    return anim
+end
\ No newline at end of file
diff --git a/helpers/PSBT_Parabola.lua b/helpers/PSBT_Parabola.lua
index a0365ee..f30b456 100644
--- a/helpers/PSBT_Parabola.lua
+++ b/helpers/PSBT_Parabola.lua
@@ -1,4 +1,5 @@
-PSBT_Parabola = {}
+local PSBT_AnimationPool = PSBT_AnimationPool
+PSBT_Parabola = PSBT_AnimationPool:Subclass()

 local PSBT_SCROLL_DIRECTIONS = PSBT_SCROLL_DIRECTIONS

@@ -10,24 +11,48 @@ local function _UP( height, progress )
     return height - _DOWN( height, progress )
 end

-function PSBT_Parabola:Calculate( height, width, points, direction )
-        local result = {}
-        local midpoint = height * 0.5
-        local fourA = ( midpoint * midpoint ) / width
-        local fn = nil
-        if ( direction == PSBT_SCROLL_DIRECTIONS.UP ) then
-            fn = _UP
-        else
-            fn = _DOWN
-        end
-
-        for i=1,points do
-                result[ i ] = { x = 0, y = 0 }
-                result[ i ].y = fn( height, i / points )
-
-                local y = result[ i ].y - midpoint
-                result[ i ].x = ( y * y ) / fourA
-        end
-
-        return result
+function PSBT_Parabola:New( height, width, points, direction )
+    local result = PSBT_AnimationPool.New( self )
+    result:Initialize( height, width, points, direction )
+    return result
 end
+
+function PSBT_Parabola:Initialize( height, width, points, direction )
+    self._parabolaPoints = {}
+
+    local midpoint = height * 0.5
+    local fourA = ( midpoint * midpoint ) / width
+    local fn = nil
+    if ( direction == PSBT_SCROLL_DIRECTIONS.UP ) then
+        fn = _UP
+    else
+        fn = _DOWN
+    end
+
+    for i=1,points do
+        self._parabolaPoints[ i ] = { x = 0, y = 0 }
+        self._parabolaPoints[ i ].y = fn( height, i / points )
+
+        local y = self._parabolaPoints[ i ].y - midpoint
+        self._parabolaPoints[ i ].x = ( y * y ) / fourA
+    end
+end
+
+function PSBT_Parabola:Create()
+    local anim = PSBT_AnimationPool.Create( self )
+
+    local points = self._parabolaPoints
+    local x, y = points[1].x, points[1].y
+    local point = nil
+    local duration = 3000 / #points
+
+    for i=1,#points do
+        point = points[ i ]
+        anim:TranslateToFrom( x, y, point.x, point.y, duration, (i - 1) * duration )
+
+        x = point.x
+        y = point.y
+    end
+
+    return anim
+end
\ No newline at end of file
diff --git a/libs/LibAnimation-1.0/LibAnimation.lua b/libs/LibAnimation-1.0/LibAnimation.lua
index dd2d5c9..16323dd 100644
--- a/libs/LibAnimation-1.0/LibAnimation.lua
+++ b/libs/LibAnimation-1.0/LibAnimation.lua
@@ -30,8 +30,8 @@ THE SOFTWARE.
 ----------------------------------------------------
 if ( not LibStub ) then return end

-local kName, kVersion = 'LibAnimation-1.0', 2.0
-local LibAnimation = LibStub:NewLibrary( kName, kVersion )
+local kName, kVersion   = 'LibAnimation-1.0', 2.1
+local LibAnimation      = LibStub:NewLibrary( kName, kVersion )
 if ( not LibAnimation ) then return end

 local AnimationMgr          = ANIMATION_MANAGER
@@ -44,7 +44,7 @@ local ANIMATION_ALPHA       = ANIMATION_ALPHA
 local _

 --- Create a new animation for control
--- @tparam table control the gui element to animate
+-- @tparam table control (optional)
 -- @tparam number playbackType (optional)
 -- @tparam number loopCount (optional)
 -- @treturn LibAnimation object
@@ -66,7 +66,7 @@ function LibAnimation:New( control, playbackType, loopCount )
 end

 --- Animation Constructor
--- @tparam table control
+-- @tparam table control (optional)
 -- @tparam number playbackType (optional)
 -- @tparam number loopCount (optional)
 function LibAnimation:Initialize( control, playbackType, loopCount )
@@ -75,6 +75,14 @@ function LibAnimation:Initialize( control, playbackType, loopCount )
     self.timeline:SetPlaybackType( playbackType, loopCount )
 end

+function LibAnimation:Apply( control )
+    self.timeline:ApplyAllAnimationsToControl( control )
+end
+
+function LibAnimation:SetHandler( ... )
+    self.timeline:SetHandler( ... )
+end
+
 --- Allows you to add a callback at a certain point in the timeline
 -- @tparam function fn
 -- @tparam number delay how long to wait before calling
@@ -109,12 +117,21 @@ function LibAnimation:Backward()
     self.timeline:PlayBackward()
 end

+function LibAnimation:SetUserData( data )
+    self._udata = data
+end
+
+function LibAnimation:GetUserData()
+    return self._udata
+end
+
 --- Get's the existing animation or creates a new one
 -- @tparam number animType
 -- @tparam number delay (optional)
 -- @tresult animation
 function LibAnimation:Insert( animType, duration, delay, anchorIndex, fn )
     local anim = self.timeline:InsertAnimation( animType, self.control, delay or 0 )
+
     anim:SetDuration( duration or 1 )
     anim:SetEasingFunction( fn or defaultEase )