Action bars: range and usable state from ClassicAPI events, drop the range ticker

Shown buttons on bars 1-10 enable C_ActionBar.EnableActionRangeCheck for
their slot and take ACTION_RANGE_CHECK_UPDATE; hiding a bar or paging
releases the old slot. ACTION_USABLE_CHANGED refreshes only the changed
slots; ACTIONBAR_UPDATE_USABLE is left to the stance buttons. Requires
ClassicAPI v1.19.1.
This commit is contained in:
Brues
2026-11-03 01:07:02 -06:00
parent cde16e7fbe
commit 1abeafcec2
2 changed files with 79 additions and 57 deletions
+1 -1
View File
@@ -13,7 +13,7 @@ do
-- on. There pfUI does load, and will throw wherever it reaches for something -- on. There pfUI does load, and will throw wherever it reaches for something
-- the installed DLL doesn't have yet -- the popup names the cause so those -- the installed DLL doesn't have yet -- the popup names the cause so those
-- errors aren't a mystery. -- errors aren't a mystery.
local PFUI_CLASSIC_API_MIN = 11900 -- (X*10000 + Y*100 + Z) local PFUI_CLASSIC_API_MIN = 11901 -- (X*10000 + Y*100 + Z)
local PFUI_CLASSIC_API_LATEST = PFUI_CLASSIC_API_MIN local PFUI_CLASSIC_API_LATEST = PFUI_CLASSIC_API_MIN
local PFUI_CLASSIC_API_WEBSITE = "https://github.com/brues-code/ClassicAPI" local PFUI_CLASSIC_API_WEBSITE = "https://github.com/brues-code/ClassicAPI"
local PFUI_CLASSIC_API_LATEST_URL = PFUI_CLASSIC_API_WEBSITE .. "/releases/latest" local PFUI_CLASSIC_API_LATEST_URL = PFUI_CLASSIC_API_WEBSITE .. "/releases/latest"
+78 -56
View File
@@ -90,7 +90,9 @@ pfUI:RegisterModule("actionbar", function ()
-- Page changes only touch the main bar, whose pager handles them. -- Page changes only touch the main bar, whose pager handles them.
local pass_events = { local pass_events = {
["ACTIONBAR_UPDATE_COOLDOWN"] = "cooldown", ["ACTIONBAR_UPDATE_COOLDOWN"] = "cooldown",
["ACTIONBAR_UPDATE_USABLE"] = "usable", -- action slots take ACTION_USABLE_CHANGED; the stance buttons still
-- need a pass on this one
["ACTIONBAR_UPDATE_USABLE"] = "stance",
["ACTIONBAR_UPDATE_STATE"] = "state", ["ACTIONBAR_UPDATE_STATE"] = "state",
-- the active border of attack, auto repeat and tradeskill actions -- the active border of attack, auto repeat and tradeskill actions
["PLAYER_ENTER_COMBAT"] = "state", ["PLAYER_ENTER_COMBAT"] = "state",
@@ -530,19 +532,18 @@ pfUI:RegisterModule("actionbar", function ()
end end
end end
local function ButtonRangeUpdate(self) -- Keeps the range check of the slot a shown action button displays
self = self or this -- enabled, so ACTION_RANGE_CHECK_UPDATE reports it. Each button holds its
-- own enable, as the client counts them per slot. An enable fires the
-- event with the current state, so a new slot starts in range until then.
local function ButtonRangeWatch(button)
local slot = C.bars.glowrange == "1" and button.bar <= 10 and button:IsVisible() and button.id or nil
if slot == button.rangeslot then return end
-- update range display if button.rangeslot then C_ActionBar.EnableActionRangeCheck(button.rangeslot, false) end
if C.bars.glowrange == "1" and self.bar ~= 11 and self.bar ~= 12 and HasAction(self.id) and ActionHasRange(self.id) and IsActionInRange(self.id) == 0 then if slot then C_ActionBar.EnableActionRangeCheck(slot, true) end
if not self.outofrange then button.rangeslot = slot
self.outofrange = true button.outofrange = nil
ButtonUsableUpdate(self)
end
elseif self.outofrange then
self.outofrange = nil
ButtonUsableUpdate(self)
end
end end
local start, duration, enable local start, duration, enable
@@ -584,7 +585,6 @@ pfUI:RegisterModule("actionbar", function ()
if not button then return end if not button then return end
ButtonSlotUpdate(button) ButtonSlotUpdate(button)
ButtonRangeUpdate(button)
ButtonUsableUpdate(button) ButtonUsableUpdate(button)
ButtonCooldownUpdate(button) ButtonCooldownUpdate(button)
end end
@@ -595,16 +595,35 @@ pfUI:RegisterModule("actionbar", function ()
-- Updates wait for the next frame, so the events of one frame share one -- Updates wait for the next frame, so the events of one frame share one
-- pass. Passes and full updates skip hidden bars, which catch up as they -- pass. Passes and full updates skip hidden bars, which catch up as they
-- show (BarShow). The shown buttons of a bar are its first `count` ones. -- show (BarShowHide). The shown buttons of a bar are its first `count` ones.
local scheduled local scheduled
-- calls func on the buttons that show a slot: its own button and the main
-- bar button paged to it
local function ForSlotButtons(slot, func, a1)
local button = buttoncache[slot]
if button then func(button, a1) end
local page = bars[1][1].id - 1
local paged = slot > page and slot <= page + 12 and bars[1][slot - page]
if paged and paged ~= button then func(paged, a1) end
end
-- the range watch follows hidden buttons too, so a hidden bar lets go of
-- its slots
local function SlotButtonUpdate(button)
ButtonRangeWatch(button)
if button:IsVisible() then pfUI.bars.ButtonFullUpdate(button) end
end
local function Flush() local function Flush()
scheduled = nil scheduled = nil
local inventory, cooldown, usable, state = passcache.inventory, passcache.cooldown, passcache.usable, passcache.state local inventory, cooldown, state = passcache.inventory, passcache.cooldown, passcache.state
local bindings = passcache.bindings local stance, bindings = passcache.stance, passcache.bindings
table.wipe(passcache) table.wipe(passcache)
if inventory or cooldown or usable or state then if inventory or cooldown or state then
for i = 1, 12 do for i = 1, 12 do
local bar = bars[i] local bar = bars[i]
if bar:IsVisible() then if bar:IsVisible() then
@@ -612,13 +631,19 @@ pfUI:RegisterModule("actionbar", function ()
local button = bar[j] local button = bar[j]
if inventory then ButtonInventoryUpdate(button) end if inventory then ButtonInventoryUpdate(button) end
if inventory or cooldown then ButtonCooldownUpdate(button) end if inventory or cooldown then ButtonCooldownUpdate(button) end
if inventory or usable then ButtonUsableUpdate(button) end if inventory then ButtonUsableUpdate(button) end
if state then ButtonIsActiveUpdate(button) end if state then ButtonIsActiveUpdate(button) end
end end
end end
end end
end end
if stance and not inventory and bars[11]:IsVisible() then
for j = 1, bars[11].count do
ButtonUsableUpdate(bars[11][j])
end
end
-- the keybinds of hidden buttons as well, as they don't catch up on them -- the keybinds of hidden buttons as well, as they don't catch up on them
if bindings then if bindings then
for _, button in pairs(buttoncache) do for _, button in pairs(buttoncache) do
@@ -627,20 +652,9 @@ pfUI:RegisterModule("actionbar", function ()
end end
end end
-- a slot refreshes its own button and the main bar button paged to it
local page = bars[1][1].id - 1
for slot in pairs(updatecache) do for slot in pairs(updatecache) do
updatecache[slot] = nil updatecache[slot] = nil
ForSlotButtons(slot, SlotButtonUpdate)
local button = buttoncache[slot]
if button and button:IsVisible() then
pfUI.bars.ButtonFullUpdate(button)
end
local paged = slot > page and slot <= page + 12 and bars[1][slot - page]
if paged and paged ~= button and paged:IsVisible() then
pfUI.bars.ButtonFullUpdate(paged)
end
end end
end end
@@ -662,28 +676,40 @@ pfUI:RegisterModule("actionbar", function ()
Schedule() Schedule()
end end
-- ClassicAPI has no range event for action slots yet, so the visible -- passes skip hidden bars, so a bar refreshes its buttons as it shows;
-- buttons are polled at the rate of the stock bars -- as it hides, its buttons let go of their range checks
local function RangeUpdate() local function BarShowHide()
for i = 1, 10 do
local bar = bars[i]
if bar:IsVisible() then
for j = 1, bar.count do
ButtonRangeUpdate(bar[j])
end
end
end
end
-- passes skip hidden bars, so a bar refreshes its buttons as it shows
local function BarShow()
local offset = (this:GetID() - 1) * 12 local offset = (this:GetID() - 1) * 12
for j = 1, this.count do for j = 1, this.count do
QueueSlot(offset + j) QueueSlot(offset + j)
end end
end end
local function ButtonRangeEvent(button, outofrange)
if button.rangeslot ~= arg1 or button.outofrange == outofrange then return end
button.outofrange = outofrange
ButtonUsableUpdate(button)
end
local function ButtonUsableEvent(button)
if button:IsVisible() then ButtonUsableUpdate(button) end
end
local function BarsEvent() local function BarsEvent()
-- slot, isInRange, checksRange of a slot a button watches
if event == "ACTION_RANGE_CHECK_UPDATE" then
ForSlotButtons(arg1, ButtonRangeEvent, arg3 and not arg2 or nil)
return
end
-- the slots whose usable state changed
if event == "ACTION_USABLE_CHANGED" then
for _, change in ipairs(arg1) do
ForSlotButtons(change.slot, ButtonUsableEvent)
end
return
end
-- refresh only specific slots -- refresh only specific slots
if event == "ACTIONBAR_SLOT_CHANGED" and arg1 and arg1 ~= 0 then if event == "ACTIONBAR_SLOT_CHANGED" and arg1 and arg1 ~= 0 then
QueueSlot(arg1) QueueSlot(arg1)
@@ -742,6 +768,8 @@ pfUI:RegisterModule("actionbar", function ()
for event in pairs(global_events) do RegisterBarEvent(event) end for event in pairs(global_events) do RegisterBarEvent(event) end
for event in pairs(aura_events) do RegisterBarEvent(event) end for event in pairs(aura_events) do RegisterBarEvent(event) end
for event in pairs(pet_events) do RegisterBarEvent(event) end for event in pairs(pet_events) do RegisterBarEvent(event) end
bars:RegisterEvent("ACTION_RANGE_CHECK_UPDATE")
bars:RegisterEvent("ACTION_USABLE_CHANGED")
-- refresh actionbar buttons on event -- refresh actionbar buttons on event
bars:SetScript("OnEvent", BarsEvent) bars:SetScript("OnEvent", BarsEvent)
@@ -1175,7 +1203,10 @@ pfUI:RegisterModule("actionbar", function ()
bars[i] = bars[i] or CreateFrame("Frame", "pfActionBar" .. barnames[i], UIParent) bars[i] = bars[i] or CreateFrame("Frame", "pfActionBar" .. barnames[i], UIParent)
bars[i]:SetID(i) bars[i]:SetID(i)
bars[i].count = buttons bars[i].count = buttons
if init then bars[i]:SetScript("OnShow", BarShow) end if init then
bars[i]:SetScript("OnShow", BarShowHide)
if i <= 10 then bars[i]:SetScript("OnHide", BarShowHide) end
end
-- autohide -- autohide
if autohide == "1" then if autohide == "1" then
@@ -1389,19 +1420,10 @@ pfUI:RegisterModule("actionbar", function ()
end end
end end
local rangeticker
pfUI.bars.UpdateConfig = function(self) pfUI.bars.UpdateConfig = function(self)
for i=1,12 do for i=1,12 do
CreateActionBar(i) CreateActionBar(i)
end end
-- poll range only while it is shown
if C.bars.glowrange == "1" and not rangeticker then
rangeticker = C_Timer.NewTicker(.2, RangeUpdate)
elseif C.bars.glowrange ~= "1" and rangeticker then
rangeticker:Cancel()
rangeticker = nil
end
end end
pfUI.bars:UpdateConfig() pfUI.bars:UpdateConfig()