From f32ede22e10760d8bb80c68f411f23177df4dcee Mon Sep 17 00:00:00 2001 From: Maczuga Date: Thu, 27 May 2021 22:40:59 +0200 Subject: [PATCH] Smooth progress ported from retail Fixes #20 --- WeakAuras/Libs/LibRetail/C_Timer.lua | 89 ++++++++++++++++++ WeakAuras/Libs/LibRetail/LibRetail.lua | 90 +----------------- WeakAuras/Libs/LibRetail/LibRetail.xml | 4 +- WeakAuras/Libs/LibRetail/SmoothStatusBar.lua | 97 ++++++++++++++++++++ WeakAuras/RegionTypes/Icon.lua | 13 ++- 5 files changed, 199 insertions(+), 94 deletions(-) create mode 100644 WeakAuras/Libs/LibRetail/C_Timer.lua create mode 100644 WeakAuras/Libs/LibRetail/SmoothStatusBar.lua diff --git a/WeakAuras/Libs/LibRetail/C_Timer.lua b/WeakAuras/Libs/LibRetail/C_Timer.lua new file mode 100644 index 0000000000..ab728cc8df --- /dev/null +++ b/WeakAuras/Libs/LibRetail/C_Timer.lua @@ -0,0 +1,89 @@ +local lib = LibStub and LibStub("LibRetail", true) +if not lib then return end + +local waitTable = {}; +local waitFrame = nil; + +function lib.After (delay, func, ...) + -- print("dupa") + if(type(delay)~="number" or type(func)~="function") then + return false; + end + if(waitFrame == nil) then + waitFrame = CreateFrame("Frame","WaitFrame", UIParent); + waitFrame:SetScript("onUpdate",function (self,elapse) + local count = #waitTable; + local i = 1; + while(i<=count) do + local waitRecord = tremove(waitTable,i); + local d = tremove(waitRecord,1); + local f = tremove(waitRecord,1); + local p = tremove(waitRecord,1); + if(d>elapse) then + tinsert(waitTable,i,{d-elapse,f,p}); + i = i + 1; + else + count = count - 1; + f(unpack(p)); + end + end + end); + end + tinsert(waitTable,{delay,func,{...}}); + return true; +end + +local TickerPrototype = {}; +local TickerMetatable = { + __index = TickerPrototype, + __metatable = true, --Probably not needed, but if I don't put this here someone is going to mess with this metatable and end up tainting everything... +}; + +--Creates and starts a ticker that calls callback every duration seconds for N iterations. +--If iterations is nil, the ticker will loop until cancelled. +-- +--If callback throws a Lua error, the ticker will stop firing. +function lib.NewTicker(duration, callback, iterations) + -- print("cnewticker") + local ticker = setmetatable({}, TickerMetatable); + ticker._remainingIterations = iterations; + ticker._callback = function() + if ( not ticker._cancelled ) then + callback(ticker); + + --Make sure we weren't cancelled during the callback + if ( not ticker._cancelled ) then + if ( ticker._remainingIterations ) then + ticker._remainingIterations = ticker._remainingIterations - 1; + end + if ( not ticker._remainingIterations or ticker._remainingIterations > 0 ) then + lib.After(duration, ticker._callback); + end + end + end + end; + + lib.After(duration, ticker._callback); + return ticker; +end + +--Creates and starts a cancellable timer that calls callback after duration seconds. +--Note that C_Timer.NewTimer is significantly more expensive than C_Timer.After and should +--only be used if you actually need any of its additional functionality. +-- +--While timers are currently just tickers with an iteration count of 1, this is likely +--to change in the future and shouldn't be relied on. +function lib.NewTimer(duration, callback) + return lib.NewTicker(duration, callback, 1); +end + +--Cancels a ticker or timer. May be safely called within the ticker's callback in which +--case the ticker simply won't be started again. +--Cancel is guaranteed to be idempotent. +function TickerPrototype:Cancel() + self._cancelled = true; +end + +function TickerPrototype:IsCancelled() + return self._cancelled; +end diff --git a/WeakAuras/Libs/LibRetail/LibRetail.lua b/WeakAuras/Libs/LibRetail/LibRetail.lua index 4ea1486b7f..dd3fd6a5cf 100644 --- a/WeakAuras/Libs/LibRetail/LibRetail.lua +++ b/WeakAuras/Libs/LibRetail/LibRetail.lua @@ -7,7 +7,7 @@ if not lib then return end LibStub("AceTimer-3.0"):Embed(lib) -- Lua APIs -local pairs, ipairs, next, select, CreateFrame, pcall = pairs, ipairs, next, select, CreateFrame, pcall +local pairs, ipairs, next, select, CreateFrame, pcall, print = pairs, ipairs, next, select, CreateFrame, pcall, print local math_abs, math_ceil, math_floor = math.abs, math.ceil, math.floor @@ -369,68 +369,6 @@ function lib.xpcall(func, errorHandler, ...) -- errorHandler(); return pcall(func, ...) end -------------------------------------- -local g_updatingBars = {}; - -local function IsCloseEnough(bar, newValue, targetValue) - local min, max = bar:GetMinMaxValues(); - local range = max - min; - if range > 0.0 then - return math_abs((newValue - targetValue) / range) < .00001; - end - - return true; -end - -local function ProcessSmoothStatusBars() - for bar, targetValue in pairs(g_updatingBars) do - local effectiveTargetValue = lib.Clamp(targetValue, bar:GetMinMaxValues()); - local newValue = lib.FrameDeltaLerp(bar:GetValue(), effectiveTargetValue, .25); - - if IsCloseEnough(bar, newValue, effectiveTargetValue) then - g_updatingBars[bar] = nil; - bar:SetValue(effectiveTargetValue); - else - bar:SetValue(newValue); - end - end -end - -lib:ScheduleRepeatingTimer(ProcessSmoothStatusBars, 0) --- C_Timer.NewTicker(0, ProcessSmoothStatusBars); - -lib.SmoothStatusBarMixin = {}; - -function lib.SmoothStatusBarMixin:ResetSmoothedValue(value) --If nil, tries to set to the last target value - local targetValue = g_updatingBars[self]; - if targetValue then - g_updatingBars[self] = nil; - self:SetValue(value or targetValue); - elseif value then - self:SetValue(value); - end -end - -function lib.SmoothStatusBarMixin:SetSmoothedValue(value) - g_updatingBars[self] = value; -end - -function lib.SmoothStatusBarMixin:SetMinMaxSmoothedValue(min, max) - self:SetMinMaxValues(min, max); - - local targetValue = g_updatingBars[self]; - if targetValue then - local ratio = 1; - if max ~= 0 and self.lastSmoothedMax and self.lastSmoothedMax ~= 0 then - ratio = max / self.lastSmoothedMax; - end - - g_updatingBars[self] = targetValue * ratio; - end - - self.lastSmoothedMin = min; - self.lastSmoothedMax = max; -end function lib.Round(value) if value < 0.0 then @@ -438,29 +376,3 @@ function lib.Round(value) end return math_floor(value + .5); end - -function lib.Clamp(value, min, max) - if value > max then - return max; - elseif value < min then - return min; - end - return value; -end - -function lib.Saturate(value) - return lib.Clamp(value, 0.0, 1.0); -end - -function lib.Lerp(startValue, endValue, amount) - return (1 - amount) * startValue + amount * endValue; -end - -local TARGET_FRAME_PER_SEC = 60.0; -function lib.DeltaLerp(startValue, endValue, amount, timeSec) - return lib.Lerp(startValue, endValue, lib.Saturate(amount * timeSec * TARGET_FRAME_PER_SEC)); -end - -function lib.FrameDeltaLerp(startValue, endValue, amount) - return lib.DeltaLerp(startValue, endValue, amount, 0.1); -end \ No newline at end of file diff --git a/WeakAuras/Libs/LibRetail/LibRetail.xml b/WeakAuras/Libs/LibRetail/LibRetail.xml index a77dc459ef..61bfadaee2 100644 --- a/WeakAuras/Libs/LibRetail/LibRetail.xml +++ b/WeakAuras/Libs/LibRetail/LibRetail.xml @@ -2,5 +2,7 @@ ..\FrameXML\UI.xsd">