diff --git a/PSBT.lua b/PSBT.lua
index 8a2a56e..bed7633 100644
--- a/PSBT.lua
+++ b/PSBT.lua
@@ -41,6 +41,12 @@ end
function PSBT:Initialize( control )
self.control = control
+
+ self._areas[ PSBT_AREAS.INCOMING ] = PSBT_ScrollArea:New( self.control, PSBT_AREAS.INCOMING, BOTTOM )
+ self._areas[ PSBT_AREAS.OUTGOING ] = PSBT_ScrollArea:New( self.control, PSBT_AREAS.OUTGOING, TOP )
+ self._areas[ PSBT_AREAS.STATIC ] = PSBT_ScrollArea:New( self.control, PSBT_AREAS.STATIC, BOTTOM )
+ self._areas[ PSBT_AREAS.NOTIFICATION ] = PSBT_ScrollArea:New( self.control, PSBT_AREAS.NOTIFICATION, TOP )
+
self.control:RegisterForEvent( EVENT_ADD_ON_LOADED, function( _, addon ) self:OnLoaded( addon ) end )
end
@@ -50,34 +56,21 @@ function PSBT:OnLoaded( addon )
end
print( 'Loading PSBT' )
-
-
- self._areas[ PSBT_AREAS.INCOMING ] = self.control:GetNamedChild( PSBT_AREAS.INCOMING )
- self._areas[ PSBT_AREAS.OUTGOING ] = self.control:GetNamedChild( PSBT_AREAS.OUTGOING )
- self._areas[ PSBT_AREAS.STATIC ] = self.control:GetNamedChild( PSBT_AREAS.STATIC )
- self._areas[ PSBT_AREAS.NOTIFICATION ] = self.control:GetNamedChild( PSBT_AREAS.NOTIFICATION )
-
- print( self._areas )
- for k,v in pairs( self._areas ) do
- print( tostring( k ) .. ' = ' ..tostring( v ) )
- end
-
-
CBM:FireCallbacks( PSBT_EVENTS.LOADED, self )
self.control:SetHandler( 'OnUpdate', function( _, frameTime ) self:OnUpdate( frameTime ) end )
end
function PSBT:OnUpdate( frameTime )
- for k,v in pairs( self._modules ) do
- v:OnUpdate( frameTime )
- end
-
for k,label in pairs( self:GetActiveObjects() ) do
- if ( not label:IsVisible() ) then
+ if ( label:IsExpired( frameTime ) ) then
self:ReleaseObject( k )
end
end
+
+ for k,v in pairs( self._modules ) do
+ v:OnUpdate( frameTime )
+ end
end
function PSBT:CreateLabel()
@@ -125,33 +118,16 @@ end
function PSBT:NewEvent( scrollArea, sticky, icon, text )
local entry = self:AcquireObject()
-
local area = self._areas[ scrollArea ]
-
- local height = area:GetHeight()
- local duration = 1
- local relativePoint = nil
- if ( scrollArea == PSBT_AREAS.NOTIFICATION ) then
- relativePoint = TOP
- duration = height * 20
- elseif ( scrollArea == PSBT_AREAS.INCOMING ) then
- relativePoint = BOTTOM
- duration = height * 10
- height = height * -1
- elseif ( scrollArea == PSBT_AREAS.OUTGOING ) then
- relativePoint = TOP
- duration = height * 10
- elseif ( scrollArea == PSBT_AREAS.STATIC ) then
- relativePoint = BOTTOM
- duration = height * 50
- height = height * -1
+ if ( not area ) then
+ return
end
- entry.control:SetAnchor( CENTER, area, relativePoint )
-
+ entry:SetExpire( -1 ) --pending
entry:SetText( text )
entry:SetTexture( icon )
- entry:Play( height, duration )
+
+ area:Push( entry, sticky )
end
-- LEAVE ME THE FUARK ALONE
diff --git a/PSBT.txt b/PSBT.txt
index 12472f7..cbec478 100644
--- a/PSBT.txt
+++ b/PSBT.txt
@@ -23,6 +23,8 @@ PSBT_Experience.lua
PSBT_LowSomething.lua
## core
+PSBT_Fifo.lua
PSBT_Label.lua
+PSBT_ScrollArea.lua
PSBT.lua
PSBT.xml
\ No newline at end of file
diff --git a/PSBT.xml b/PSBT.xml
index b312e86..12f499a 100644
--- a/PSBT.xml
+++ b/PSBT.xml
@@ -4,16 +4,13 @@
<Dimensions x="300" y="24" />
<Controls>
- <Texture name="$(parent)_Icon" layer="OVERLAY">
- <Dimensions x="24" />
- <Anchor point="TOPLEFT" relativeTo="$(parent)" relativePoint="TOPLEFT" />
- <Anchor point="BOTTOMLEFT" relativeTo="$(parent)" relativePoint="BOTTOMLEFT" />
- </Texture>
-
- <Label name="$(parent)_Name" font="ZoFontGameBold" horizontalAlignment="LEFT" verticalAlignment="CENTER" wrapMode="ELLIPSIS">
- <Anchor point="TOPLEFT" relativeTo="$(parent)_Icon" relativePoint="TOPRIGHT" offsetX="2" offsetY="2" />
- <Anchor point="BOTTOMRIGHT" relativeTo="$(parent)" relativePoint="BOTTOMRIGHT" offsetX="-2" offsetY="-2" />
+ <Label name="$(parent)_Name" font="ZoFontGameBold" horizontalAlignment="CENTER" verticalAlignment="CENTER" wrapMode="ELLIPSIS">
+ <AnchorFill/>
</Label>
+
+ <Texture name="$(parent)_Icon" layer="OVERLAY" visible="false">
+ <Dimensions x="24" y="24" />
+ </Texture>
</Controls>
</Control>
@@ -27,6 +24,7 @@
<Dimensions x="500" y="60" />
<Anchor point="CENTER" relativeTo="$(parent)" relativePoint="CENTER" offsetX="0" offsetY="450" />
<Controls>
+ <!--<Texture name="$(parent)BG" inherits="ZO_ThinListBgStrip" />-->
</Controls>
</Control>
@@ -34,6 +32,7 @@
<Dimensions x="500" y="60" />
<Anchor point="CENTER" relativeTo="$(parent)" relativePoint="CENTER" offsetX="0" offsetY="-300" />
<Controls>
+ <!--<Texture name="$(parent)BG" inherits="ZO_ThinListBgStrip" />-->
</Controls>
</Control>
@@ -41,6 +40,7 @@
<Dimensions x="300" y="450" />
<Anchor point="RIGHT" relativeTo="$(parent)" relativePoint="CENTER" offsetX="-300" offsetY="150" />
<Controls>
+ <!--<Texture name="$(parent)BG" inherits="ZO_ThinListBgStrip" />-->
</Controls>
</Control>
@@ -48,6 +48,7 @@
<Dimensions x="300" y="450" />
<Anchor point="LEFT" relativeTo="$(parent)" relativePoint="CENTER" offsetX="300" offsetY="150" />
<Controls>
+ <!--<Texture name="$(parent)BG" inherits="ZO_ThinListBgStrip" />-->
</Controls>
</Control>
</Controls>
diff --git a/PSBT_Auras.lua b/PSBT_Auras.lua
index 5e2e269..625864e 100644
--- a/PSBT_Auras.lua
+++ b/PSBT_Auras.lua
@@ -22,11 +22,11 @@ function PSBT_Auras:OnEffectChanged( changeType, effectSlot, effectName, unitTag
end
function PSBT_Auras:Add( name, iconName )
- self:NewEvent( PSBT_AREAS.NOTIFICATION, false, iconName, name .. ' Gained' )
+ self:NewEvent( PSBT_AREAS.NOTIFICATION, true, iconName, name .. ' Gained' )
end
function PSBT_Auras:Remove( name, iconName )
- self:NewEvent( PSBT_AREAS.NOTIFICATION, false, iconName, name .. ' Fades' )
+ self:NewEvent( PSBT_AREAS.NOTIFICATION, true, iconName, name .. ' Fades' )
end
CBM:RegisterCallback( PSBT_EVENTS.LOADED,
diff --git a/PSBT_Combat.lua b/PSBT_Combat.lua
index b3197e2..5882676 100644
--- a/PSBT_Combat.lua
+++ b/PSBT_Combat.lua
@@ -319,9 +319,9 @@ local combat_events =
function PSBT_Combat:Initialize( ... )
PSBT_Module.Initialize( self, ... )
- self._buffer = ZO_CircularBuffer:New( DEFAULT_MAX_BUFFERED_EVENTS )
- self._index = 1
- self._free = nil
+ self._buffer = ZO_CircularBuffer:New( DEFAULT_MAX_BUFFERED_EVENTS )
+ self._index = 1
+ self._free = nil
for i=1,GetNumAbilities() do
local name, icon = GetAbilityInfoByIndex( i )
@@ -339,15 +339,13 @@ function PSBT_Combat:OnCombatEvent( ... )
-- did we get hit or do something?
if ( IsPlayer( select( 7, ... ), select( 6, ... ) ) or IsPlayer( select( 9, ... ), select( 8, ... ) ) ) then
-
if ( self._free ) then
local argCount = select( "#", ... )
- for i = 1,argCount do
+ for i = 1, argCount do
self._free[ i ] = select( i, ... )
end
- --clear any additional arguments
- for i=#self._free,argCount+1,-1 do
+ for i = #self._free,argCount + 1, -1 do
self._free[ i ] = nil
end
@@ -364,18 +362,20 @@ function PSBT_Combat:OnUpdate( frameTime )
if ( self._index <= 0 ) then
self._index = 1
end
-
- local size = self._buffer:Size()
- local stop = zo_min( self._index + MAX_EVENTS, size )
- for i=self._index,stop do
- local iterator = self._buffer:At( i )
- if ( iterator ) then
- self:DispatchEvent( unpack( iterator ) )
+
+ local bufferSize = self._buffer:Size()
+ local endPoint = zo_min( self._index + MAX_EVENTS, bufferSize )
+ for i = self._index, endPoint do
+ local entry = self._buffer:At( i )
+ if ( entry ) then
+ self:DispatchEvent( unpack( entry ) )
end
- end
+ end
- if ( stop <= size ) then
- self._index = stop + 1
+ if ( endPoint >= bufferSize ) then
+ self._buffer:Clear()
+ else
+ self._index = endPoint + 1
end
end
diff --git a/PSBT_Experience.lua b/PSBT_Experience.lua
index 0b80ce9..ca46f19 100644
--- a/PSBT_Experience.lua
+++ b/PSBT_Experience.lua
@@ -25,7 +25,7 @@ function PSBT_Experience:OnXPUpdated( tag, exp, maxExp, reason )
self._currentExperience = xp
if ( gain <= 0 ) then return end
- self:NewEvent( PSBT_AREAS.INCOMING, false, nil, '+' .. tostring( gain ) .. ' XP' )
+ self:NewEvent( PSBT_AREAS.NOTIFICATION, true, nil, '+' .. tostring( gain ) .. ' XP' )
end
diff --git a/PSBT_Fifo.lua b/PSBT_Fifo.lua
new file mode 100644
index 0000000..702e7a9
--- /dev/null
+++ b/PSBT_Fifo.lua
@@ -0,0 +1,87 @@
+------
+-- 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/PSBT_Label.lua b/PSBT_Label.lua
index 2c943d3..7ffd91c 100644
--- a/PSBT_Label.lua
+++ b/PSBT_Label.lua
@@ -14,45 +14,59 @@ function PSBT_Label:Initialize( objectPool )
self.control = CreateControlFromVirtual( 'PSBT_Label', self.objectPool.control, 'PSBT_Label', self.objectPool:GetNextControlId() )
self.label = self.control:GetNamedChild( '_Name' )
self.icon = self.control:GetNamedChild( '_Icon' )
+ self.expire = 0
+ self.moving = false
+
+ self.control:SetAlpha( 0.0 )
end
-function PSBT_Label:Finalize()
- self.label:SetText( '' )
- self.icon:SetTexture( 0 )
- self.control:SetHidden( true )
+function PSBT_Label:SetMoving( set )
+ self.moving = set
end
-function PSBT_Label:SetText( text )
- self.label:SetText( text )
+function PSBT_Label:IsMoving()
+ return self.moving
end
-function PSBT_Label:SetTexture( texture )
- if ( type( texture ) == 'string' ) then
- self.icon:SetWidth( self.control:GetHeight() )
- self.icon:SetTexture( texture )
- else
- self.icon:SetWidth( 0 )
+function PSBT_Label:SetExpire( expire )
+ self.expire = expire
+end
+
+function PSBT_Label:WillExpire( frameTime )
+ return frameTime > self.expire
+end
+
+function PSBT_Label:IsExpired( frameTime )
+ if ( self.expire == -1 ) then
+ return false
end
+
+ if ( self.moving ) then
+ return false
+ end
+
+ return frameTime > self.expire
end
-function PSBT_Label:IsVisible()
- return self.control:GetAlpha() > 0.001
+function PSBT_Label:Finalize()
+ self:SetText( '' )
+ self:SetTexture( 0 )
+ self:SetExpire( 0 )
+ self:SetMoving( false )
end
-function PSBT_Label:Play( height, duration )
- self.control:SetHidden( false )
- self.control:SetAlpha( 0.01 )
+function PSBT_Label:SetText( text )
+ self.label:SetText( text )
- local enter = LibAnim:New( self.control )
- enter:AlphaTo( 1.0, 500, nil, nil, ZO_LinearEase )
- enter:InsertCallback( function() self:OnEnterComplete( height, duration ) end, 500 )
- enter:Play()
+ local textWidth = self.label:GetTextDimensions()
+ self.icon:SetAnchor( CENTER, self.control, CENTER, ( textWidth * -0.45 ) - self.icon:GetWidth(), 0 )
end
-function PSBT_Label:OnEnterComplete( height, duration )
- local leave = LibAnim:New( self.control )
- leave:AlphaTo( 0.0, duration, nil, nil, ZO_EaseOutCubic )
- leave:TranslateTo( 0, height, duration, nil, nil, ZO_EaseOutCubic )
-
- leave:Play()
+function PSBT_Label:SetTexture( texture )
+ if ( type( texture ) == 'string' ) then
+ self.icon:SetHidden( false )
+ self.icon:SetTexture( texture )
+ else
+ self.icon:SetHidden( true )
+ end
end
\ No newline at end of file
diff --git a/PSBT_LowSomething.lua b/PSBT_LowSomething.lua
index 4946719..f5e76a6 100644
--- a/PSBT_LowSomething.lua
+++ b/PSBT_LowSomething.lua
@@ -51,7 +51,7 @@ function PSBT_LowSomething:OnPowerUpdate( unit, powerPoolIndex, powerType, power
string = 'Mount Stamina Low! (|c0CF2B9' .. powerPool .. '|r)'
end
- self:NewEvent( PSBT_AREAS.STATIC, false, nil, string )
+ self:NewEvent( PSBT_AREAS.STATIC, true, nil, string )
end
CBM:RegisterCallback( PSBT_EVENTS.LOADED,
diff --git a/PSBT_ScrollArea.lua b/PSBT_ScrollArea.lua
new file mode 100644
index 0000000..9fcb65b
--- /dev/null
+++ b/PSBT_ScrollArea.lua
@@ -0,0 +1,140 @@
+local tinsert = table.insert
+local tremove = table.remove
+
+PSBT_ScrollArea = ZO_Object:Subclass()
+
+local LibAnim = LibStub( 'LibAnimation-1.0' )
+if ( not LibAnim ) then return end
+
+local NUM_STICKY = 4
+
+function PSBT_ScrollArea:New( ... )
+ local result = ZO_Object.New( self )
+ result:Initialize( ... )
+ return result
+end
+
+function PSBT_ScrollArea:Initialize( super, areaName, anchor )
+ self.control = super:GetNamedChild( areaName )
+ self._anchor = anchor
+ self._animHeight = nil
+ self._newSticky = false
+ self._sticky = PSBT_Fifo.New()
+ self._pendingSticky = PSBT_Fifo.New()
+ self._normal = {}
+ self._pendingNormal = PSBT_Fifo.New()
+
+ if ( anchor == TOP ) then
+ self._animHeight = self.control:GetHeight()
+ else
+ self._animHeight = -1 * self.control:GetHeight()
+ end
+
+ self.control:SetHandler( 'OnUpdate', function( event, ... ) self:OnUpdate( ... ) end )
+end
+
+function PSBT_ScrollArea:Push( entry, sticky )
+ if ( sticky ) then
+ entry.control:SetAnchor( CENTER, self.control, CENTER, 0, self.control:GetHeight() )
+ self._pendingSticky:Push( entry )
+ return
+ end
+
+ entry.control:SetAnchor( CENTER, self.control, self._anchor, 0, 0 )
+ self._pendingNormal:Push( entry )
+end
+
+function PSBT_ScrollArea:OnUpdate( frameTime )
+ 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()
+
+ 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 )
+ anim:TranslateTo( 0, -200, 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 ( newEntry ) then
+ newEntry:SetExpire( frameTime + 5 )
+
+ local anim = LibAnim:New( newEntry.control )
+ anim:AlphaTo( 1.0, 200 )
+ anim:Play()
+
+ tinsert( self._normal, newEntry )
+ end
+ end
+
+ if ( self._pendingSticky:Size() ) then
+ local newEntry = self._pendingSticky:Pop()
+ if ( newEntry ) then
+ newEntry:SetExpire( frameTime + 5 )
+
+ local anim = LibAnim:New( newEntry.control )
+ anim:AlphaTo( 1.0, 200 )
+ anim:Play()
+
+ self._sticky:Push( newEntry )
+ self._newSticky = true
+ end
+ end
+
+ local i = 1
+ while ( i <= #self._normal ) do
+ local entry = self._normal[ i ]
+
+ if ( entry:WillExpire( frameTime + 2 ) ) then
+ local anim = LibAnim:New( entry.control )
+ anim:AlphaTo( 0.0, 200 )
+ anim:Play()
+
+ entry:SetMoving( false )
+
+ tremove( self._normal, i )
+ else
+ if ( not entry:IsMoving() ) then
+ local anim = LibAnim:New( entry.control )
+ anim:TranslateTo( 0, self._animHeight, 3000 )
+ 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()
+
+ entry:SetMoving( true )
+
+ top = top + entry.control:GetHeight()
+ end
+ end
+
+ self._newSticky = false
+end
\ No newline at end of file