PSBT_ScrollArea = ZO_Object:Subclass() local CBM = CALLBACK_MANAGER local tinsert = table.insert local tremove = table.remove local NUM_STICKY = 4 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 ) result:Initialize( ... ) return result end 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 = {} self._pendingSticky = {} self._normal = {} self._pendingNormal = {} self._fadeIn = fadeIn self._fadeOut = fadeOut 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:SetConfigurationMode( enable ) self.control:SetMovable( enable ) self.control:SetMouseEnabled( enable ) self.label:SetHidden( not enable ) if ( enable ) then local anim = self._fadeIn:Apply( self.background ) anim:Play() else local anim = self._fadeOut:Apply( self.background ) anim:Play() end end function PSBT_ScrollArea:Position( settings ) self.control:SetAnchor( settings.to, self.control:GetParent(), settings.from, settings.x, settings.y ) end function PSBT_ScrollArea:GetAnchorOffsets() local _, point, _, relPoint, offsX, offsY = self.control:GetAnchor( 0 ) return point, relPoint, offsX, offsY end function PSBT_ScrollArea:AnchorChild( control, sticky ) local rel = CENTER local from = CENTER if ( not sticky ) then rel = TOP end control:SetAnchor( from, self.control, rel, 0, 0 ) end function PSBT_ScrollArea:Push( entry, sticky ) self:AnchorChild( entry.control, sticky ) entry:SetIconPosition( self._iconSide ) if ( sticky ) then tinsert( self._pendingSticky, entry ) else tinsert( self._pendingNormal, entry ) end end function PSBT_ScrollArea:SetSettings( settings ) 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 and not #self._normal and not #self._pendingNormal and not #self._pendingSticky ) then return end while ( #self._sticky > NUM_STICKY ) do local old = tremove( self._sticky, 1 ) old:SetMoving( false ) old:SetExpire( frameTime ) self._newSticky = true end if ( #self._pendingNormal and #self._normal < 25 ) then local newEntry = tremove( self._pendingNormal, 1 ) if ( newEntry ) then newEntry:SetExpire( frameTime + 3 ) local anim = self._fadeIn:Apply( newEntry.control ) anim:Play() tinsert( self._normal, newEntry ) end end if ( #self._pendingSticky ) then local newEntry = tremove( self._pendingSticky, 1 ) if ( newEntry ) then newEntry:SetExpire( frameTime + 5 ) local anim = self._fadeIn:Apply( newEntry.control ) anim:Play() tinsert( self._sticky, newEntry ) self._newSticky = true end end local i = 1 local entry = nil while ( i <= #self._normal ) do entry = self._normal[ i ] 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._parabola:Apply( entry.control ) anim:Play() entry:SetMoving( true ) end i = i + 1 end end i = 1 local top = 0 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() 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 self._newSticky = false end