You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
250 lines
7.2 KiB
250 lines
7.2 KiB
---------------------------------------------------------------
|
|
-- Animation.lua: Taint-free animation framework
|
|
---------------------------------------------------------------
|
|
-- Provides a framework for managing alpha animations without
|
|
-- risk of spreading taint, which might happen when the "real"
|
|
-- functions are called from secure code.
|
|
|
|
local _, L = ...
|
|
|
|
---------------------------------------------------------------
|
|
-- Fade: Taint-free fade functions
|
|
---------------------------------------------------------------
|
|
|
|
local FADEFRAMES = {}
|
|
local FadeManager = CreateFrame("Frame")
|
|
|
|
local function FadeRemoveFrame(frame)
|
|
tDeleteItem(FADEFRAMES, frame)
|
|
end
|
|
|
|
local function FadeOnUpdate(self, elapsed)
|
|
local index = 1
|
|
local frame, fadeInfo
|
|
while FADEFRAMES[index] do
|
|
frame = FADEFRAMES[index]
|
|
fadeInfo = FADEFRAMES[index].fadeInfo
|
|
-- Reset the timer if there isn't one, this is just an internal counter
|
|
if ( not fadeInfo.fadeTimer ) then
|
|
fadeInfo.fadeTimer = 0
|
|
end
|
|
fadeInfo.fadeTimer = fadeInfo.fadeTimer + elapsed
|
|
|
|
-- If the fadeTimer is less then the desired fade time then set the alpha otherwise hold the fade state, call the finished function, or just finish the fade
|
|
if fadeInfo.fadeTimer < fadeInfo.timeToFade then
|
|
if fadeInfo.mode == "IN" then
|
|
frame:SetAlpha((fadeInfo.fadeTimer / fadeInfo.timeToFade) * (fadeInfo.endAlpha - fadeInfo.startAlpha) + fadeInfo.startAlpha)
|
|
elseif fadeInfo.mode == "OUT" then
|
|
frame:SetAlpha(((fadeInfo.timeToFade - fadeInfo.fadeTimer) / fadeInfo.timeToFade) * (fadeInfo.startAlpha - fadeInfo.endAlpha) + fadeInfo.endAlpha)
|
|
end
|
|
else
|
|
frame:SetAlpha(fadeInfo.endAlpha)
|
|
-- If there is a fadeHoldTime then wait until its passed to continue on
|
|
if fadeInfo.fadeHoldTime and fadeInfo.fadeHoldTime > 0 then
|
|
fadeInfo.fadeHoldTime = fadeInfo.fadeHoldTime - elapsed
|
|
else
|
|
-- Complete the fade and call the finished function if there is one
|
|
FadeRemoveFrame(frame)
|
|
if fadeInfo.finishedFunc then
|
|
fadeInfo.finishedFunc(fadeInfo.finishedArg1, fadeInfo.finishedArg2, fadeInfo.finishedArg3, fadeInfo.finishedArg4)
|
|
fadeInfo.finishedFunc = nil
|
|
end
|
|
end
|
|
end
|
|
|
|
index = index + 1
|
|
end
|
|
|
|
if #FADEFRAMES == 0 then
|
|
self:SetScript("OnUpdate", nil)
|
|
end
|
|
end
|
|
|
|
-- Generic fade function
|
|
local function FadeFrame(frame, fadeInfo)
|
|
if not frame then
|
|
return
|
|
end
|
|
if not fadeInfo.mode then
|
|
fadeInfo.mode = "IN"
|
|
end
|
|
local alpha
|
|
if fadeInfo.mode == "IN" then
|
|
if not fadeInfo.startAlpha then
|
|
fadeInfo.startAlpha = 0
|
|
end
|
|
if not fadeInfo.endAlpha then
|
|
fadeInfo.endAlpha = 1.0
|
|
end
|
|
alpha = 0
|
|
elseif fadeInfo.mode == "OUT" then
|
|
if not fadeInfo.startAlpha then
|
|
fadeInfo.startAlpha = 1.0
|
|
end
|
|
if not fadeInfo.endAlpha then
|
|
fadeInfo.endAlpha = 0
|
|
end
|
|
alpha = 1.0
|
|
end
|
|
frame:SetAlpha(fadeInfo.startAlpha)
|
|
|
|
frame.fadeInfo = fadeInfo
|
|
|
|
local index = 1
|
|
while FADEFRAMES[index] do
|
|
-- If frame is already set to fade then return
|
|
if FADEFRAMES[index] == frame then
|
|
return
|
|
end
|
|
index = index + 1
|
|
end
|
|
tinsert(FADEFRAMES, frame)
|
|
FadeManager:SetScript("OnUpdate", FadeOnUpdate)
|
|
end
|
|
|
|
-- Convenience function for simple fade in
|
|
L.UIFrameFadeIn = function (frame, timeToFade, startAlpha, endAlpha, info)
|
|
local fadeInfo = info or {}
|
|
fadeInfo.mode = "IN"
|
|
fadeInfo.timeToFade = timeToFade
|
|
fadeInfo.startAlpha = startAlpha
|
|
fadeInfo.endAlpha = endAlpha
|
|
FadeFrame(frame, fadeInfo)
|
|
end
|
|
|
|
-- Convenience function for simple fade out
|
|
L.UIFrameFadeOut = function (frame, timeToFade, startAlpha, endAlpha, info)
|
|
local fadeInfo = info or {}
|
|
fadeInfo.mode = "OUT"
|
|
fadeInfo.timeToFade = timeToFade
|
|
fadeInfo.startAlpha = startAlpha
|
|
fadeInfo.endAlpha = endAlpha
|
|
FadeFrame(frame, fadeInfo)
|
|
end
|
|
|
|
-- Expose removal of frame from fader
|
|
L.UIFrameStopFading = function(frame)
|
|
FadeRemoveFrame(frame)
|
|
end
|
|
|
|
|
|
---------------------------------------------------------------
|
|
-- Flash: Taint-free flash functions
|
|
---------------------------------------------------------------
|
|
local FlashManager = CreateFrame("FRAME")
|
|
local FLASHFRAMES = {}
|
|
|
|
local FlashTimers = {}
|
|
local FlashTimerRefCount = {}
|
|
|
|
-- Function to stop flashing
|
|
local function FlashStop(frame)
|
|
tDeleteItem(FLASHFRAMES, frame)
|
|
frame:SetAlpha(1.0)
|
|
frame.flashTimer = nil
|
|
if frame.syncId then
|
|
FlashTimerRefCount[frame.syncId] = FlashTimerRefCount[frame.syncId]-1
|
|
if FlashTimerRefCount[frame.syncId] == 0 then
|
|
FlashTimers[frame.syncId] = nil
|
|
FlashTimerRefCount[frame.syncId] = nil
|
|
end
|
|
frame.syncId = nil
|
|
end
|
|
if frame.showWhenDone then
|
|
frame:Show()
|
|
else
|
|
frame:Hide()
|
|
end
|
|
end
|
|
|
|
-- Called every frame to update flashing frames
|
|
local function FlashOnUpdate(self, elapsed)
|
|
local frame
|
|
local index = #FLASHFRAMES
|
|
|
|
-- Update timers for all synced frames
|
|
for syncId, timer in pairs(FlashTimers) do
|
|
FlashTimers[syncId] = timer + elapsed
|
|
end
|
|
|
|
while FLASHFRAMES[index] do
|
|
frame = FLASHFRAMES[index]
|
|
frame.flashTimer = frame.flashTimer + elapsed
|
|
|
|
if (frame.flashTimer > frame.flashDuration) and frame.flashDuration ~= -1 then
|
|
FlashStop(frame)
|
|
else
|
|
local flashTime = frame.flashTimer
|
|
local alpha
|
|
|
|
if frame.syncId then
|
|
flashTime = FlashTimers[frame.syncId]
|
|
end
|
|
|
|
flashTime = flashTime%(frame.fadeInTime+frame.fadeOutTime+(frame.flashInHoldTime or 0)+(frame.flashOutHoldTime or 0))
|
|
if flashTime < frame.fadeInTime then
|
|
alpha = flashTime/frame.fadeInTime
|
|
elseif flashTime < frame.fadeInTime+(frame.flashInHoldTime or 0) then
|
|
alpha = 1
|
|
elseif flashTime < frame.fadeInTime+(frame.flashInHoldTime or 0)+frame.fadeOutTime then
|
|
alpha = 1 - ((flashTime - frame.fadeInTime - (frame.flashInHoldTime or 0))/frame.fadeOutTime)
|
|
else
|
|
alpha = 0
|
|
end
|
|
|
|
frame:SetAlpha(alpha)
|
|
frame:Show()
|
|
end
|
|
|
|
-- Loop in reverse so that removing frames is safe
|
|
index = index - 1
|
|
end
|
|
|
|
if #FLASHFRAMES == 0 then
|
|
self:SetScript("OnUpdate", nil)
|
|
end
|
|
end
|
|
|
|
-- Function to start a frame flashing
|
|
L.UIFrameFlash = function(frame, fadeInTime, fadeOutTime, flashDuration, showWhenDone, flashInHoldTime, flashOutHoldTime, syncId)
|
|
if frame then
|
|
local index = 1
|
|
-- If frame is already set to flash then return
|
|
while FLASHFRAMES[index] do
|
|
if FLASHFRAMES[index] == frame then
|
|
return
|
|
end
|
|
index = index + 1
|
|
end
|
|
|
|
if syncId then
|
|
frame.syncId = syncId
|
|
if FlashTimers[syncId] == nil then
|
|
FlashTimers[syncId] = 0
|
|
FlashTimerRefCount[syncId] = 0
|
|
end
|
|
FlashTimerRefCount[syncId] = FlashTimerRefCount[syncId]+1
|
|
else
|
|
frame.syncId = nil
|
|
end
|
|
|
|
-- Time it takes to fade in a flashing frame
|
|
frame.fadeInTime = fadeInTime
|
|
-- Time it takes to fade out a flashing frame
|
|
frame.fadeOutTime = fadeOutTime
|
|
-- How long to keep the frame flashing
|
|
frame.flashDuration = flashDuration
|
|
-- Show the flashing frame when the fadeOutTime has passed
|
|
frame.showWhenDone = showWhenDone
|
|
-- Internal timer
|
|
frame.flashTimer = 0
|
|
-- How long to hold the faded in state
|
|
frame.flashInHoldTime = flashInHoldTime
|
|
-- How long to hold the faded out state
|
|
frame.flashOutHoldTime = flashOutHoldTime
|
|
|
|
tinsert(FLASHFRAMES, frame)
|
|
|
|
FlashManager:SetScript("OnUpdate", FlashOnUpdate)
|
|
end
|
|
end
|
|
|