Port unitframe and actionbar performance fixes from Duciel/pfUI@45f8ca6

Unitframes: only set the unit attribute when it changes, poll group frame indicators every 3s since events already cover them, and limit full refreshes on eventless frames to unit changes or once a second.

Actionbar: handle UNIT_INVENTORY_CHANGED with a light count/cooldown/usable pass instead of a full update of every button, and skip hidden buttons in the cached passes, catching them up once they become visible.
This commit is contained in:
Brues
2026-10-23 12:39:07 -05:00
parent 6aaf4f2047
commit e7e1382693
2 changed files with 88 additions and 29 deletions
+33 -7
View File
@@ -318,10 +318,16 @@ function pfUI.uf:UpdateVisibility()
self._label, self._id = nil, nil
end
local unitstr = ("%s%s"):format(self.label or "", self.id or "")
self.unitstr = unitstr ~= "" and unitstr or nil
self:SetAttribute("unit", self.unitstr)
local visibility = ("[target=%s,exists] show; hide"):format(unitstr)
-- this runs for every frame five times a second, so only touch the
-- attribute when the unit actually changed
local unitstr = (self.label or "") .. (self.id or "")
local unit = unitstr ~= "" and unitstr or nil
if unit ~= self.unitstr then
self.unitstr = unit
self:SetAttribute("unit", unit)
end
-- anything but "show"/"hide" means "show if the unit exists"
local visibility = "exists"
-- Group frames are redundant when the group is already shown as a raid grid:
-- either an actual raid, or a party promoted to the raid grid via
@@ -1088,7 +1094,18 @@ function pfUI.uf.OnUpdate()
end
else
pfUI.uf:RefreshUnitState(this)
pfUI.uf:RefreshIndicators(this)
-- group frames get their leader/loot/raid mark icons refreshed by
-- events through update_indicators, so polling them is only a safety
-- net; frames whose unit changes without events keep polling per tick
local label = this.label
if label == "raid" or label == "party" or label == "raidpet" or label == "partypet" then
if (this.lastIndicatorPoll or 0) < now then
this.lastIndicatorPoll = now + 3
pfUI.uf:RefreshIndicators(this)
end
else
pfUI.uf:RefreshIndicators(this)
end
end
if this.config and this.config.glowaggro == "1" and pfUI.api.UnitHasAggro(unitstr) > 0 then
@@ -1101,9 +1118,18 @@ function pfUI.uf.OnUpdate()
this.glow:Hide()
end
-- update everything on eventless frames (targettarget, etc)
-- update eventless frames (targettarget, etc). A full refresh rescans
-- every aura and the portrait, so only do it when the unit behind the
-- frame changes or once a second; other ticks refresh the bars only.
if this.tick then
pfUI.uf:RefreshUnit(this, "all")
local guid = UnitGUID(unitstr)
if guid ~= this.tickGuid or (this.tickFull or 0) < now then
this.tickGuid = guid
this.tickFull = now + 1
pfUI.uf:RefreshUnit(this, "all")
else
pfUI.uf:RefreshUnit(this, "base")
end
end
end
+55 -22
View File
@@ -81,6 +81,9 @@ pfUI:RegisterModule("actionbar", function ()
["ACTIONBAR_UPDATE_COOLDOWN"] = true,
["ACTIONBAR_UPDATE_USABLE"] = true,
["ACTIONBAR_UPDATE_STATE"] = true,
-- fires on every ammo shot / consumable use, but only counts, equipped
-- state, cooldowns and usability can change from it
["UNIT_INVENTORY_CHANGED"] = true,
}
-- events that are shared across all buttons
@@ -97,8 +100,6 @@ pfUI:RegisterModule("actionbar", function ()
["TRADE_SKILL_CLOSE"] = true,
["PLAYER_ENTER_COMBAT"] = true,
["PLAYER_LEAVE_COMBAT"] = true,
-- cooldown updates
["UNIT_INVENTORY_CHANGED"] = true,
-- auto repeat action
["START_AUTOREPEAT_SPELL"] = true,
["STOP_AUTOREPEAT_SPELL"] = true,
@@ -400,6 +401,28 @@ pfUI:RegisterModule("actionbar", function ()
GameTooltip:Hide()
end
-- item counts and equipped border, the parts of a slot an inventory change touches
local function ButtonInventoryUpdate(self)
if self.bar == 11 or self.bar == 12 then return end
local sid = self.id
-- update consumables
if IsConsumableAction(sid) then
self.count:SetText(GetActionCount(sid))
elseif IsReagentAction and IsReagentAction(sid) then
self.count:SetText(GetReagentCount(sid))
else
self.count:SetText(nil)
end
-- equipped item
if IsEquippedAction(sid) and C.bars.showequipped == "1" then
self.equipped:Show()
else
self.equipped:Hide()
end
end
local start, duration, enable, castable, autocast, token
local grid, sid, id, bar, active, texture, _
local function ButtonSlotUpdate(self)
@@ -460,23 +483,9 @@ pfUI:RegisterModule("actionbar", function ()
self.active:Hide()
end
ButtonInventoryUpdate(self)
if self.bar ~= 11 and self.bar ~= 12 then
-- update consumables
if IsConsumableAction(sid) then
self.count:SetText(GetActionCount(sid))
elseif IsReagentAction and IsReagentAction(sid) then
self.count:SetText(GetReagentCount(sid))
else
self.count:SetText(nil)
end
-- equipped item
if IsEquippedAction(sid) and C.bars.showequipped == "1" then
self.equipped:Show()
else
self.equipped:Hide()
end
-- update macro text
if C.bars["bar"..self.bar] and C.bars["bar"..self.bar].showmacro == "1" then
self.macro:SetText(GetActionText(sid))
@@ -696,11 +705,29 @@ pfUI:RegisterModule("actionbar", function ()
end
end
-- The cached passes below only touch visible buttons. Hidden ones (other
-- pages, hidden bars) are flagged stale and get a full update once the
-- range pass sees them visible again.
-- run cached inventory changes (ammo, reagents, consumables)
if eventcache["UNIT_INVENTORY_CHANGED"] then
eventcache["UNIT_INVENTORY_CHANGED"] = nil
for id, button in pairs(buttoncache) do
if button:IsVisible() then
ButtonInventoryUpdate(button)
ButtonCooldownUpdate(button)
ButtonUsableUpdate(button)
else
button.stale = true
end
end
end
-- run cached usable usable actions
if eventcache["ACTIONBAR_UPDATE_USABLE"] then
eventcache["ACTIONBAR_UPDATE_USABLE"] = nil
for id, button in pairs(buttoncache) do
ButtonUsableUpdate(button)
if button:IsVisible() then ButtonUsableUpdate(button) else button.stale = true end
end
end
@@ -708,7 +735,7 @@ pfUI:RegisterModule("actionbar", function ()
if eventcache["ACTIONBAR_UPDATE_COOLDOWN"] then
eventcache["ACTIONBAR_UPDATE_COOLDOWN"] = nil
for id, button in pairs(buttoncache) do
ButtonCooldownUpdate(button)
if button:IsVisible() then ButtonCooldownUpdate(button) else button.stale = true end
end
end
@@ -716,7 +743,7 @@ pfUI:RegisterModule("actionbar", function ()
if eventcache["ACTIONBAR_UPDATE_STATE"] then
eventcache["ACTIONBAR_UPDATE_STATE"] = nil
for id, button in pairs(buttoncache) do
ButtonIsActiveUpdate(button)
if button:IsVisible() then ButtonIsActiveUpdate(button) else button.stale = true end
end
end
@@ -738,7 +765,13 @@ pfUI:RegisterModule("actionbar", function ()
if ( this.tick or .2) > GetTime() then return else this.tick = GetTime() + .2 end
for id, button in pairs(buttoncache) do
if button:IsShown() then ButtonRangeUpdate(button) end
if button.stale and button:IsVisible() then
-- catch up on updates skipped while hidden
button.stale = nil
ButtonFullUpdate(button)
elseif button:IsShown() then
ButtonRangeUpdate(button)
end
end
end