local E, L, V, P, G = unpack(ElvUI) -- Credit: ls- (lightspark) local abs, next, Lerp = abs, next, Lerp local tonumber, assert = tonumber, assert local activeObjects = {} local handledObjects = {} local TARGET_FPS = 60 local AMOUNT = 0.33 local frame = CreateFrame('Frame') function E:Smoothing_Clamp(v, min, max) if not min then min = 0 end if not max then max = 1 end if v > max then return max elseif v < min then return min end return v end function E:Smoothing_IsCloseEnough(new, target, range) if range > 0 then return abs((new - target) / range) <= 0.001 end return true end function E:Smoothing_OnUpdate(elapsed) for object, target in next, activeObjects do local new = Lerp(object._value, target, E:Smoothing_Clamp(AMOUNT * elapsed * TARGET_FPS)) if E:Smoothing_IsCloseEnough(new, target, object._max - object._min) then new = target activeObjects[object] = nil end object:SetValue_(new) object._value = new end end function E:Smoothing_SetSmoothedValue(value) value = tonumber(value) assert(value, 'bar_SetSmoothedValue requires (value) to be a number.') self._value = self:GetValue() activeObjects[self] = E:Smoothing_Clamp(value, self._min, self._max) end function E:Smoothing_SetSmoothedMinMaxValues(min, max) min, max = tonumber(min), tonumber(max) assert(min and max, 'bar_SetSmoothedMinMaxValues requires (min and max) to be a number.') self:SetMinMaxValues_(min, max) if self._max and self._max ~= max then local ratio = 1 if max ~= 0 and self._max and self._max ~= 0 then ratio = max / (self._max or max) end local target = activeObjects[self] if target then activeObjects[self] = target * ratio end local cur = self._value if cur then self:SetValue_(cur * ratio) self._value = cur * ratio end end self._min = min self._max = max end function E:Smoothing_Enable(bar) bar._min, bar._max = bar:GetMinMaxValues() bar._value = bar:GetValue() if not bar.SetValue_ then bar.SetValue_ = bar.SetValue bar.SetValue = E.Smoothing_SetSmoothedValue end if not bar.SetMinMaxValues_ then bar.SetMinMaxValues_ = bar.SetMinMaxValues bar.SetMinMaxValues = E.Smoothing_SetSmoothedMinMaxValues end if not frame:GetScript('OnUpdate') then frame:SetScript('OnUpdate', E.Smoothing_OnUpdate) end handledObjects[bar] = true end function E:Smoothing_Disable(bar) if activeObjects[bar] then bar:SetValue_(activeObjects[bar]) activeObjects[bar] = nil end if handledObjects[bar] then handledObjects[bar] = nil end if bar.SetValue_ then bar.SetValue = bar.SetValue_ bar.SetValue_ = nil end if bar.SetMinMaxValues_ then bar.SetMinMaxValues = bar.SetMinMaxValues_ bar.SetMinMaxValues_ = nil end if not next(handledObjects) then frame:SetScript('OnUpdate', nil) end end function E:SetSmoothingAmount(amount) AMOUNT = E:Smoothing_Clamp(amount, 0.2, 0.8) end function E:SetSmoothing(bar, enable) if enable then E:Smoothing_Enable(bar) else E:Smoothing_Disable(bar) end end