Skip to content

Commit ef1d864

Browse files
committed
feat: Meta Icons and Icon Shown conditions now use pure event-driven updates.
1 parent ca9e422 commit ef1d864

File tree

8 files changed

+228
-93
lines changed

8 files changed

+228
-93
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
## v11.2.5
2+
* Meta Icons and Icon Shown conditions now use pure event-driven updates. This is made possible by dynamic, dependency-aware ordering of icon update checks. If you have circular dependencies between icons, you may find that some updates may be delayed by at least one update interval.
23
* While Condition Set Passing and On Condition Set Passing triggers for notifications no longer evaluate while their icon's group is not shown/active. This now matches the behavior of all other notification triggers.
4+
* Unit Conditions no longer evaluate while the icon that requested them is not shown/active.
35

46
## v11.2.4
57
* Fix Spells.lua:27: attempt to index field "SpellBookSpellBank" (a nil value)

Components/Core/Conditions/Categories/Misc.lua

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -59,25 +59,21 @@ ConditionCategory:RegisterCondition(1, "ICON", {
5959
unit = false,
6060
icon = "Interface\\Icons\\INV_Misc_PocketWatch_01",
6161
tcoords = CNDT.COMMON.standardtcoords,
62-
Env = {
63-
IsIconShown = function(icon)
64-
if not icon or not icon.attributes.shown then return false end
65-
icon:Update()
66-
return icon.attributes.realAlpha > 0
67-
end
68-
},
6962
funcstr = function(c, icon)
7063
TMW:QueueValidityCheck(icon, c.Icon, L["VALIDITY_CONDITION_DESC"])
7164

72-
return "BOOLCHECK(IsIconShown(c.Icon))"
65+
return "BOOLCHECK(c.Icon and c.Icon.attributes.shown and c.Icon.attributes.realAlpha > 0)"
7366
end,
74-
--[[events = function(ConditionObject, c)
67+
events = function(ConditionObject, c)
7568
local event = TMW.Classes.IconDataProcessor.ProcessorsByName.REALALPHA.changedEvent
7669
ConditionObject:RequestEvent(event)
70+
local event2 = TMW.Classes.IconDataProcessor.ProcessorsByName.SHOWN.changedEvent
71+
ConditionObject:RequestEvent(event2)
72+
7773
ConditionObject:SetNumEventArgs(1)
7874
return
79-
"event == '" .. event .. "' and arg1:GetGUID() == " .. format("%q", c.Icon)
80-
end,]]
75+
"(event == '" .. event .. "' or event == '" .. event2 .. "') and arg1:GetGUID() == " .. format("%q", c.Icon)
76+
end,
8177
})
8278

8379
local function RegisterShownHiddenTimerCallback()
@@ -163,6 +159,19 @@ TMW:RegisterCallback("TMW_EXPORT_SETTINGS_REQUESTED", function(event, strings, t
163159
end
164160
end)
165161

162+
-- Collect icon dependencies from conditions
163+
TMW:RegisterCallback("TMW_COLLECT_ICON_DEPENDENCIES", function(event, icon, dependencies)
164+
if icon and icon.Conditions then
165+
for n, conditionSettings in TMW:InNLengthTable(icon.Conditions) do
166+
local GUID = conditionSettings.Icon
167+
if GUID and GUID ~= "" then
168+
tinsert(dependencies, GUID)
169+
end
170+
end
171+
end
172+
end)
173+
174+
166175

167176
ConditionCategory:RegisterCondition(3, "MOUSEOVER", {
168177
text = L["MOUSEOVERCONDITION"],

Components/Core/Icon.lua

Lines changed: 118 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -179,8 +179,116 @@ function Icon.ScriptSort(iconA, iconB)
179179
end
180180
return gA < gB
181181
end
182-
Icon:UpdateTable_SetAutoSort(Icon.ScriptSort)
183-
TMW:RegisterCallback("TMW_GLOBAL_UPDATE_POST", Icon, "UpdateTable_PerformAutoSort")
182+
183+
-- Dependency-aware sorting function
184+
local function SortIconUpdateTable(icons)
185+
-- First, collect all dependencies for all icons
186+
local iconDependencies = {}
187+
local iconsByGUID = {}
188+
local iconsInTable = {}
189+
190+
-- Build lookup tables
191+
for i = 1, #icons do
192+
local icon = icons[i]
193+
iconsInTable[icon] = i
194+
local iconGUID = icon:GetGUID()
195+
if iconGUID then
196+
iconsByGUID[iconGUID] = icon
197+
end
198+
end
199+
200+
-- Collect dependencies for each icon
201+
for i = 1, #icons do
202+
local icon = icons[i]
203+
local dependencies = {}
204+
205+
-- Fire the dependency collection event
206+
TMW:Fire("TMW_COLLECT_ICON_DEPENDENCIES", icon, dependencies)
207+
208+
-- Filter dependencies to only include icons that are actually in the update table
209+
local filteredDeps = {}
210+
for _, depGUID in ipairs(dependencies) do
211+
local depIcon = TMW.GUIDToOwner[depGUID]
212+
if depIcon and iconsInTable[depIcon] then
213+
tinsert(filteredDeps, depIcon)
214+
end
215+
end
216+
217+
iconDependencies[icon] = filteredDeps
218+
end
219+
220+
-- Perform topological sort with fallback to original sort for cycles
221+
local sorted = {}
222+
local visiting = {}
223+
local visited = {}
224+
local hasCycle = {}
225+
226+
local function visit(icon)
227+
if visiting[icon] then
228+
-- Cycle detected
229+
hasCycle[icon] = true
230+
return
231+
end
232+
if visited[icon] then
233+
return
234+
end
235+
236+
visiting[icon] = true
237+
238+
-- Visit all dependencies first
239+
local deps = iconDependencies[icon] or {}
240+
for _, depIcon in ipairs(deps) do
241+
if not hasCycle[depIcon] then
242+
visit(depIcon)
243+
end
244+
end
245+
246+
visiting[icon] = nil
247+
visited[icon] = true
248+
tinsert(sorted, icon)
249+
end
250+
251+
-- Sort icons by the original criteria first to maintain deterministic order
252+
local iconsCopy = {}
253+
for i = 1, #icons do
254+
iconsCopy[i] = icons[i]
255+
end
256+
sort(iconsCopy, Icon.ScriptSort)
257+
258+
-- Visit all icons in the original sort order
259+
for _, icon in ipairs(iconsCopy) do
260+
if not visited[icon] and not hasCycle[icon] then
261+
visit(icon)
262+
end
263+
end
264+
265+
-- Add any icons that were part of cycles at the end, in original sort order
266+
for _, icon in ipairs(iconsCopy) do
267+
if hasCycle[icon] and not visited[icon] then
268+
tinsert(sorted, icon)
269+
visited[icon] = true
270+
end
271+
end
272+
273+
-- Copy the sorted result back to the original array
274+
for i = 1, #sorted do
275+
icons[i] = sorted[i]
276+
end
277+
end
278+
279+
-- Debounced sorting triggered by icon setup changes
280+
-- By triggering on icon setup instead of TMW_GLOBAL_UPDATE_POST,
281+
-- we can perform sorting after icons and groups are enabled/disabled with slash commands.
282+
local sortUpdateQueued = false
283+
TMW:RegisterCallback("TMW_ICON_SETUP_POST", function()
284+
if not sortUpdateQueued then
285+
sortUpdateQueued = true
286+
C_Timer.After(0, function()
287+
sortUpdateQueued = false
288+
SortIconUpdateTable(TMW.IconsToUpdate)
289+
end)
290+
end
291+
end)
184292

185293
-- [WRAPPER] (no documentation needed)
186294
Icon.SetScript_Blizz = Icon.SetScript
@@ -581,6 +689,14 @@ function Icon.SetUpdateMethod(icon, method)
581689
end
582690
end
583691

692+
--- Gets the update method that is being used by the icon.
693+
-- @name Icon:GetUpdateMethod
694+
-- @paramsig
695+
-- @return [string] The update method being used by the icon ("auto" or "manual")
696+
function Icon.GetUpdateMethod(icon)
697+
return icon.Update_Method or "auto"
698+
end
699+
584700
-- [INTERNAL] (no documentation needed)
585701
function Icon.ScheduleNextUpdate(icon)
586702
local time = TMW.time

Components/Core/Utils.lua

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,13 @@ Formatter{
8787

8888
D_SECONDS = Formatter:New(D_SECONDS),
8989
S_SECONDS = Formatter:New(L["ANIM_SECONDS"]),
90+
S_SECONDS_UPS = Formatter:New(function(value)
91+
if value == 0 then
92+
return L["UIPANEL_UPDATEINTERVAL_UPS"]:format(0.001, 1000)
93+
else
94+
return L["UIPANEL_UPDATEINTERVAL_UPS"]:format(value, ("%d"):format(1/value))
95+
end
96+
end),
9097

9198
PIXELS = Formatter:New(L["ANIM_PIXELS"]),
9299

0 commit comments

Comments
 (0)