Refactor progress handling

probably some regressions
This commit is contained in:
NoM0Re
2025-01-22 03:37:10 +01:00
parent a643b275ba
commit 23c7da5ea6
29 changed files with 2037 additions and 1263 deletions
+301 -187
View File
@@ -11,67 +11,11 @@ function Private.regionPrototype.AddAlphaToDefault(default)
default.alpha = 1.0;
end
-- Adjusted Duration
function Private.regionPrototype.AddAdjustedDurationToDefault(default)
default.useAdjustededMax = false;
default.useAdjustededMin = false;
end
function Private.regionPrototype.AddAdjustedDurationOptions(options, data, order)
options.useAdjustededMin = {
type = "toggle",
width = WeakAuras.normalWidth,
name = L["Set Minimum Progress"],
desc = L["Values/Remaining Time below this value are displayed as no progress."],
order = order
};
options.adjustedMin = {
type = "input",
validate = WeakAuras.ValidateNumericOrPercent,
width = WeakAuras.normalWidth,
order = order + 0.01,
name = L["Minimum"],
hidden = function() return not data.useAdjustededMin end,
desc = L["Enter static or relative values with %"]
};
options.useAdjustedMinSpacer = {
type = "description",
width = WeakAuras.normalWidth,
name = "",
order = order + 0.02,
hidden = function() return not (not data.useAdjustededMin and data.useAdjustededMax) end,
};
options.useAdjustededMax = {
type = "toggle",
width = WeakAuras.normalWidth,
name = L["Set Maximum Progress"],
desc = L["Values/Remaining Time above this value are displayed as full progress."],
order = order + 0.03
};
options.adjustedMax = {
type = "input",
width = WeakAuras.normalWidth,
validate = WeakAuras.ValidateNumericOrPercent,
order = order + 0.04,
name = L["Maximum"],
hidden = function() return not data.useAdjustededMax end,
desc = L["Enter static or relative values with %"]
};
options.useAdjustedMaxSpacer = {
type = "description",
width = WeakAuras.normalWidth,
name = "",
order = order + 0.05,
hidden = function() return not (data.useAdjustededMin and not data.useAdjustededMax) end,
};
return options;
-- Progress Sources
function Private.regionPrototype.AddProgressSourceToDefault(default)
default.progressSource = {-1, ""}
default.useAdjustededMax = false
default.useAdjustededMin = false
end
local screenWidth, screenHeight = math.ceil(GetScreenWidth() / 20) * 20, math.ceil(GetScreenHeight() / 20) * 20;
@@ -149,6 +93,28 @@ function Private.regionPrototype.AddProperties(properties, defaultsForRegion)
isPercent = true
}
end
if defaultsForRegion and defaultsForRegion.progressSource then
properties["progressSource"] = {
display = L["Progress Source"],
setter = "SetProgressSource",
type = "progressSource",
values = {},
}
properties["adjustedMin"] = {
display = L["Minimum Progress"],
setter = "SetAdjustedMin",
type = "string",
validate = WeakAuras.ValidateNumericOrPercent,
}
properties["adjustedMax"] = {
display = L["Maximum Progress"],
setter = "SetAdjustedMax",
type = "string",
validate = WeakAuras.ValidateNumericOrPercent,
}
end
end
local function SoundRepeatStop(self)
@@ -373,62 +339,253 @@ local function GetRegionAlpha(self)
return self.animAlpha or self.alpha or 1;
end
local function SetProgressSource(self, progressSource)
self.progressSource = progressSource
self:UpdateProgress()
end
local function SetAdjustedMin(self, adjustedMin)
local percent = string.match(adjustedMin, "(%d+)%%")
if percent then
self.adjustedMinRelPercent = tonumber(percent) / 100
self.adjustedMin = nil
else
self.adjustedMin = tonumber(adjustedMin)
self.adjustedMinRelPercent = nil
end
self:UpdateProgress()
end
local function SetAdjustedMax(self, adjustedMax)
local percent = string.match(adjustedMax, "(%d+)%%")
if percent then
self.adjustedMaxRelPercent = tonumber(percent) / 100
else
self.adjustedMax = tonumber(adjustedMax)
end
self:UpdateProgress()
end
local function GetProgressSource(self)
return self.progressSource
end
local function GetMinMaxProgress(self)
return self.minProgress or 0, self.maxProgress or 0
end
local function UpdateProgressFromState(self, minMaxConfig, state, progressSource)
local progressType = progressSource[2]
local property = progressSource[3]
local totalProperty = progressSource[4]
local inverseProperty = progressSource[5]
local pausedProperty = progressSource[6]
local remainingProperty = progressSource[7]
if progressType == "number" then
local value = state[property] or 0
local total = totalProperty and state[totalProperty] or 0
-- We don't care about inverse or paused
local adjustMin
if minMaxConfig.adjustedMin then
adjustMin = minMaxConfig.adjustedMin
elseif minMaxConfig.adjustedMinRelPercent then
adjustMin = minMaxConfig.adjustedMinRelPercent * total
else
adjustMin = 0
end
local max
if minMaxConfig.adjustedMax then
max = minMaxConfig.adjustedMax
elseif minMaxConfig.adjustedMaxRelPercent then
max = minMaxConfig.adjustedMaxRelPercent * total
else
max = total
end
-- The output of UpdateProgress is setting various values on self
-- and calling UpdateTime/UpdateValue. Not an ideal interface, but
-- the animation code/sub elements needs those values in some convenient place
self.minProgress, self.maxProgress = adjustMin, max
self.progressType = "static"
self.value = value - adjustMin
self.total = max - adjustMin
if self.UpdateValue then
self:UpdateValue()
end
elseif progressType == "timer" then
local expirationTime
local paused = pausedProperty and state[pausedProperty]
local inverse = inverseProperty and state[inverseProperty]
local remaining
if paused then
remaining = remainingProperty and state[remainingProperty]
expirationTime = GetTime() + (remaining or 0)
else
expirationTime = state[property] or math.huge
end
local duration = totalProperty and state[totalProperty] or 0
local adjustMin
if minMaxConfig.adjustedMin then
adjustMin = minMaxConfig.adjustedMin
elseif minMaxConfig.adjustedMinRelPercent then
adjustMin = minMaxConfig.adjustedMinRelPercent * duration
else
adjustMin = 0
end
local max
if minMaxConfig.adjustedMax then
max = minMaxConfig.adjustedMax
elseif minMaxConfig.adjustedMaxRelPercent then
max = minMaxConfig.adjustedMaxRelPercent * duration
else
max = duration
end
self.minProgress, self.maxProgress = adjustMin, max
self.progressType = "timed"
self.duration = max - adjustMin
self.expirationTime = expirationTime - adjustMin
self.remaining = remaining
self.inverse = inverse
self.paused = paused
if self.UpdateTime then
self:UpdateTime()
end
elseif progressType == "elapsedTimer" then
local startTime = state[property] or math.huge
local duration = totalProperty and state[totalProperty] or 0
local adjustMin
if minMaxConfig.adjustedMin then
adjustMin = minMaxConfig.adjustedMin
elseif minMaxConfig.adjustedMinRelPercent then
adjustMin = minMaxConfig.adjustedMinRelPercent * duration
else
adjustMin = 0
end
local max
if minMaxConfig.adjustedMax then
max = minMaxConfig.adjustedMax
elseif minMaxConfig.adjustedMaxRelPercent then
max = minMaxConfig.adjustedMaxRelPercent * duration
else
max = duration
end
self.minProgress, self.maxProgress = adjustMin, max
self.progressType = "timed"
self.duration = max - adjustMin
self.expirationTime = startTime + adjustMin + self.duration
self.inverse = true
self.paused = false
self.remaining = nil
if self.UpdateTime then
self:UpdateTime()
end
end
end
local autoTimedProgressSource = {-1, "timer", "expirationTime", "duration", "inverse", "paused", "remaining"}
local autoStaticProgressSource = {-1, "number", "value", "total", nil, nil, nil, nil}
local function UpdateProgressFromAuto(self, minMaxConfig, state)
if state.progressType == "timed" then
UpdateProgressFromState(self, minMaxConfig, state, autoTimedProgressSource)
elseif state.progressType == "static"then
UpdateProgressFromState(self, minMaxConfig, state, autoStaticProgressSource)
else
self.minProgress, self.maxProgress = nil, nil
self.progressType = "timed"
self.duration = 0
self.expirationTime = math.huge
self.inverse = false
self.paused = true
self.remaining = math.huge
if self.UpdateTime then
self:UpdateTime()
end
end
end
local function UpdateProgressFromManual(self, minMaxConfig, state, value, total)
value = type(value) == "number" and value or 0
total = type(total) == "number" and total or 0
local adjustMin
if minMaxConfig.adjustedMin then
adjustMin = minMaxConfig.adjustedMin
elseif minMaxConfig.adjustedMinRelPercent then
adjustMin = minMaxConfig.adjustedMinRelPercent * total
else
adjustMin = 0
end
local max
if minMaxConfig.adjustedMax then
max = minMaxConfig.adjustedMax
elseif minMaxConfig.adjustedMaxRelPercent then
max = minMaxConfig.adjustedMaxRelPercent * total
else
max = total
end
self.minProgress, self.maxProgress = adjustMin, max
self.progressType = "static"
self.value = value - adjustMin
self.total = max - adjustMin
if self.UpdateValue then
self:UpdateValue()
end
end
local function UpdateProgressFrom(self, progressSource, minMaxConfig, state, states, parent)
local trigger = progressSource and progressSource[1] or -1
if trigger == -2 then
-- sub element'a auto uses the whatever progress the main region has
UpdateProgressFromAuto(self, minMaxConfig, parent)
elseif trigger == -1 then
-- auto for regions uses the state
UpdateProgressFromAuto(self, minMaxConfig, state)
elseif trigger == 0 then
UpdateProgressFromManual(self, minMaxConfig, state, progressSource[3], progressSource[4])
else
UpdateProgressFromState(self, minMaxConfig, states[trigger] or {}, progressSource)
end
end
-- For regions
local function UpdateProgress(self)
UpdateProgressFrom(self, self.progressSource, self, self.state, self.states)
end
Private.UpdateProgressFrom = UpdateProgressFrom
local function SetAnimAlpha(self, alpha)
if alpha then
if alpha > 1 then
alpha = 1
elseif alpha < 0 then
alpha = 0
end
end
if (self.animAlpha == alpha) then
return;
end
self.animAlpha = alpha;
local errorHandler = Private.GetErrorHandlerId(self.id, L["Custom Fade Animation"])
if (WeakAuras.IsOptionsOpen()) then
local ok = pcall(self.SetAlpha, self, max(self.animAlpha or self.alpha or 1, 0.5))
if not ok then
Private.GetErrorHandlerId(self.id, L["Custom Fade Animation"])
errorHandler()
end
else
local ok = pcall(self.SetAlpha, self, self.animAlpha or self.alpha or 1)
if not ok then
Private.GetErrorHandlerId(self.id, L["Custom Fade Animation"])
errorHandler()
end
end
self.subRegionEvents:Notify("AlphaChanged")
end
local function SetTriggerProvidesTimer(self, timerTick)
self.triggerProvidesTimer = timerTick
self:UpdateTimerTick()
end
local function TimerTickForRegion(region)
Private.StartProfileSystem("timer tick")
Private.StartProfileAura(region.id);
region.subRegionEvents:Notify("TimerTick")
Private.StopProfileAura(region.id);
Private.StopProfileSystem("timer tick")
end
local function UpdateTimerTick(self)
if self.triggerProvidesTimer and self.subRegionEvents:HasSubscribers("TimerTick") and self.toShow then
if not self:GetScript("OnUpdate") then
self:SetScript("OnUpdate", function()
TimerTickForRegion(self)
end);
end
else
if self:GetScript("OnUpdate") then
self:SetScript("OnUpdate", nil);
end
end
end
local function UpdateFrameTick(self)
local function UpdateTick(self)
if self.subRegionEvents:HasSubscribers("FrameTick") and self.toShow then
Private.FrameTick:AddSubscriber("FrameTick", self)
Private.FrameTick:AddSubscriber("Tick", self)
else
Private.FrameTick:RemoveSubscriber("FrameTick", self)
Private.FrameTick:RemoveSubscriber("Tick", self)
end
end
local function FrameTick(self)
local function Tick(self)
Private.StartProfileAura(self.id)
self.values.lastCustomTextUpdate = nil
self.subRegionEvents:Notify("FrameTick")
@@ -484,12 +641,18 @@ function Private.regionPrototype.create(region)
region.SetRegionAlpha = SetRegionAlpha;
region.GetRegionAlpha = GetRegionAlpha;
end
if defaultsForRegion and defaultsForRegion.progressSource then
region.SetProgressSource = SetProgressSource
region.GetProgressSource = GetProgressSource
region.SetAdjustedMin = SetAdjustedMin
region.SetAdjustedMax = SetAdjustedMax
end
region.UpdateProgress = UpdateProgress
region.GetMinMaxProgress = GetMinMaxProgress
region.SetAnimAlpha = SetAnimAlpha;
region.SetTriggerProvidesTimer = SetTriggerProvidesTimer
region.UpdateTimerTick = UpdateTimerTick
region.UpdateFrameTick = UpdateFrameTick
region.FrameTick = FrameTick
region.UpdateTick = UpdateTick
region.Tick = Tick
region.subRegionEvents = Private.CreateSubscribableObject()
region.AnchorSubRegion = AnchorSubRegion
@@ -498,14 +661,12 @@ function Private.regionPrototype.create(region)
region:SetPoint("CENTER", UIParent, "CENTER")
end
-- SetDurationInfo
function Private.regionPrototype.modify(parent, region, data)
region.state = nil
region.states = nil
region.subRegionEvents:ClearSubscribers()
region.subRegionEvents:ClearCallbacks()
Private.FrameTick:RemoveSubscriber("FrameTick", region)
Private.FrameTick:RemoveSubscriber("Tick", region)
local defaultsForRegion = Private.regionTypes[data.regionType] and Private.regionTypes[data.regionType].default;
@@ -513,18 +674,20 @@ function Private.regionPrototype.modify(parent, region, data)
region:SetRegionAlpha(data.alpha)
end
local hasAdjustedMin = defaultsForRegion and defaultsForRegion.useAdjustededMin ~= nil and data.useAdjustededMin
and data.adjustedMin;
local hasAdjustedMax = defaultsForRegion and defaultsForRegion.useAdjustededMax ~= nil and data.useAdjustededMax
and data.adjustedMax;
local hasProgressSource = defaultsForRegion and defaultsForRegion.progressSource
local hasAdjustedMin = hasProgressSource and data.useAdjustededMin and data.adjustedMin
local hasAdjustedMax = hasProgressSource and data.useAdjustededMax and data.adjustedMax
region.progressSource = nil
region.adjustedMin = nil
region.adjustedMinRel = nil
region.adjustedMinRelPercent = nil
region.adjustedMax = nil
region.adjustedMaxRel = nil
region.adjustedMaxRelPercent = nil
if hasProgressSource then
region.progressSource = Private.AddProgressSourceMetaData(data, data.progressSource)
end
if (hasAdjustedMin) then
local percent = string.match(data.adjustedMin, "(%d+)%%")
if percent then
@@ -576,7 +739,7 @@ function Private.regionPrototype.modify(parent, region, data)
data.actions.start[fullKey] = default
end
return data.actions.start[fullKey]
end, true)
end, true, data)
region.finishFormatters = Private.CreateFormatters(data.actions.finish.message, function(key, default)
local fullKey = "message_format_" .. key
@@ -584,7 +747,7 @@ function Private.regionPrototype.modify(parent, region, data)
data.actions.finish[fullKey] = default
end
return data.actions.finish[fullKey]
end, true)
end, true, data)
end
function Private.regionPrototype.modifyFinish(parent, region, data)
@@ -615,91 +778,56 @@ function Private.regionPrototype.modifyFinish(parent, region, data)
end
end
region.subRegionEvents:SetOnSubscriptionStatusChanged("TimerTick", function()
region:UpdateTimerTick()
end)
region:UpdateTimerTick()
region.subRegionEvents:SetOnSubscriptionStatusChanged("FrameTick", function()
region:UpdateFrameTick()
region:UpdateTick()
end)
region:UpdateFrameTick()
region:UpdateTick()
Private.ApplyFrameLevel(region)
end
local function SetProgressValue(region, value, total)
local adjustMin = region.adjustedMin or 0;
local max = region.adjustedMax or total;
region:SetValue(value - adjustMin, max - adjustMin);
end
local regionsForFrameTick = {}
local frameForFrameTick = CreateFrame("Frame");
Private.frames["Frame Tick Frame"] = frameForFrameTick
Private.FrameTick = Private.CreateSubscribableObject()
Private.FrameTick.OnUpdateHandler = function()
if WeakAuras.IsOptionsOpen() then
return
end
Private.StartProfileSystem("frame tick")
Private.FrameTick:Notify("FrameTick")
Private.FrameTick:Notify("Tick")
Private.StopProfileSystem("frame tick")
end
Private.FrameTick:SetOnSubscriptionStatusChanged("FrameTick", function()
if Private.FrameTick:HasSubscribers("FrameTick") then
Private.FrameTick:SetOnSubscriptionStatusChanged("Tick", function()
if Private.FrameTick:HasSubscribers("Tick") then
frameForFrameTick:SetScript("OnUpdate", Private.FrameTick.OnUpdateHandler);
else
frameForFrameTick:SetScript("OnUpdate", nil)
end
end)
local function TimerTickForSetDuration(self)
local duration = self.duration
local adjustMin = self.adjustedMin or 0;
local max
if duration == 0 then
max = 0
elseif self.adjustedMax then
max = self.adjustedMax
else
max = duration
end
self:SetTime(max - adjustMin, self.expirationTime - adjustMin, self.inverse);
end
function Private.regionPrototype.AddSetDurationInfo(region)
if (region.SetValue and region.SetTime) then
region.generatedSetDurationInfo = true;
-- WeakAuras no longer calls SetDurationInfo, but some people do that,
-- In that case we also need to overwrite TimerTick
function Private.regionPrototype.AddSetDurationInfo(region, uid)
if (region.UpdateValue and region.UpdateTime) then
-- WeakAuras no longer calls SetDurationInfo, but some people do that
region.SetDurationInfo = function(self, duration, expirationTime, customValue, inverse)
self.duration = duration or 0
self.expirationTime = expirationTime;
self.inverse = inverse;
-- For now don't warn against SetDurationInfo
-- Private.AuraWarnings.UpdateWarning(uid, "SetDurationInfo", "warning", L["Aura is using deprecated SetDurationInfo"])
if customValue then
SetProgressValue(region, duration, expirationTime);
region.TimerTick = nil
region.subRegionEvents:RemoveSubscriber("TimerTick", self)
else
local adjustMin = region.adjustedMin or 0;
region:SetTime((duration ~= 0 and region.adjustedMax or duration) - adjustMin, expirationTime - adjustMin, inverse);
region.TimerTick = TimerTickForSetDuration
region.subRegionEvents:AddSubscriber("TimerTick", self, true)
local max = self.adjustedMax or expirationTime
region.progressType = "static"
region.value = duration - adjustMin
region.total = max - adjustMin
region:UpdateValue()
else
local adjustMin = self.adjustedMin or 0;
self.progressType = "timed"
self.duration = (duration ~= 0 and self.adjustedMax or duration) - adjustMin
self.expirationTime = expirationTime - adjustMin
self.inverse = inverse
self.paused = false
self.remaining = nil
self:UpdateTime()
end
end
elseif (region.generatedSetDurationInfo) then
region.generatedSetDurationInfo = nil;
region.SetDurationInfo = nil;
end
end
@@ -808,8 +936,7 @@ function Private.regionPrototype.AddExpandFunction(data, region, cloneId, parent
region:SoundRepeatStop();
end
region:UpdateFrameTick()
region:UpdateTimerTick()
region:UpdateTick()
end
function region:Expand()
if (region.toShow) then
@@ -844,8 +971,7 @@ function Private.regionPrototype.AddExpandFunction(data, region, cloneId, parent
end
parent:ActivateChild(data.id, cloneId);
region:UpdateFrameTick()
region:UpdateTimerTick()
region:UpdateTick()
end
elseif not(data.controlledChildren) then
function region:Collapse()
@@ -867,8 +993,7 @@ function Private.regionPrototype.AddExpandFunction(data, region, cloneId, parent
region:SoundRepeatStop();
end
region:UpdateFrameTick()
region:UpdateTimerTick()
region:UpdateTick()
end
function region:Expand()
if data.anchorFrameType == "SELECTFRAME"
@@ -915,8 +1040,7 @@ function Private.regionPrototype.AddExpandFunction(data, region, cloneId, parent
parent:UpdateBorder(region);
end
region:UpdateFrameTick()
region:UpdateTimerTick()
region:UpdateTick()
end
end
-- Stubs that allow for polymorphism
@@ -926,16 +1050,6 @@ function Private.regionPrototype.AddExpandFunction(data, region, cloneId, parent
if not region.Expand then
function region:Expand() end
end
if not region.Pause then
function region:Pause()
self.paused = true
end
end
if not region.Resume then
function region:Resume()
self.paused = nil
end
end
end
do