Compare commits

..
3 Commits
Author SHA1 Message Date
Brues 494f176f18 Nameplates: stay in the world stratum, raise the target by level
The overlay inherits the engine plate's world stratum, below every UI
stratum. Moving it to BACKGROUND/LOW put it level-for-level against the
chat panels, so plates drew over the chat. The target now rises above
the other plates by raising its engine frame and re-parenting the
overlay, which carries the subtree's levels along. Debuff icons take
their level from the health bar so ones grown on a raised plate stay
above it.
2026-11-02 01:36:06 -06:00
Brues 8f1b3dc39b Cooldowns: size the numbers from OnSizeChanged, not timer starts
Buff buttons start their timers before they are sized, so their numbers took
the height-0 font and kept it until a timer restarted.
2026-11-02 01:18:59 -06:00
Brues 23d25c4791 Focus target: follow its token, not its GUID
The focus target frame filtered its unit events on the unit's GUID, which
only arrive while nampower fires its raw-GUID events (NP_EnableUnitEventsGuid
on, NP_EnableUnitEventsGuidFiltering off) and SuperWoW watches every unit.
Without them the bars froze until the focus switched targets (#76).

ClassicAPI fires the focus target's unit events as "focustarget" and the
focus's UNIT_TARGET as "focus" whatever nampower does, so the frame follows
those tokens. The swap check keeps its own GUID cache, since eventunit is
no longer a GUID for that frame.
2026-11-02 01:06:17 -06:00
4 changed files with 56 additions and 31 deletions
+12 -11
View File
@@ -58,14 +58,17 @@ function pfUI.api.GetCooldownFontSize(height)
return size return size
end end
-- sizes the numbers to the cooldown's parent; the size follows its height, -- sizes the numbers to the height of the frame the cooldown covers
-- so a timer start calls this again whenever that height changed local function UpdateFont(cooldown, height)
local function UpdateFont(cooldown)
local height = (cooldown:GetParent() or cooldown):GetHeight()
cooldown.pfCountdownHeight = height
cooldown:GetCountdownFontString():SetFont(pfUI.media[C.cooldown.font], pfUI.api.GetCooldownFontSize(height), "OUTLINE") cooldown:GetCountdownFontString():SetFont(pfUI.media[C.cooldown.font], pfUI.api.GetCooldownFontSize(height), "OUTLINE")
end end
-- a pfUI cooldown covers its parent, so it resizes with it; a hidden one is
-- laid out, and this runs, as it shows
local function OnSizeChanged(cooldown, width, height)
UpdateFont(cooldown, height)
end
-- applies the settings of its kind to one of pfUI's cooldowns -- applies the settings of its kind to one of pfUI's cooldowns
local function SetupCooldown(cooldown) local function SetupCooldown(cooldown)
local kind = cooldown.pfCooldownKind local kind = cooldown.pfCooldownKind
@@ -78,7 +81,7 @@ local function SetupCooldown(cooldown)
cooldown:SetReverse(config.reverse == "1") cooldown:SetReverse(config.reverse == "1")
cooldown:SetMinimumCountdownDuration(spell[kind] and tonumber(C.cooldown.threshold) * 1000 or 0) cooldown:SetMinimumCountdownDuration(spell[kind] and tonumber(C.cooldown.threshold) * 1000 or 0)
cooldown:SetCountdownFormatter(GetFormatter()) cooldown:SetCountdownFormatter(GetFormatter())
UpdateFont(cooldown) UpdateFont(cooldown, cooldown:GetParent():GetHeight())
end end
-- applies the "foreign" settings to another addon's cooldown. They only take -- applies the "foreign" settings to another addon's cooldown. They only take
@@ -100,18 +103,15 @@ local function SetupForeign(cooldown)
cooldown:SetMinimumCountdownDuration(tonumber(C.cooldown.threshold) * 1000) cooldown:SetMinimumCountdownDuration(tonumber(C.cooldown.threshold) * 1000)
cooldown:SetCountdownFormatter(GetFormatter()) cooldown:SetCountdownFormatter(GetFormatter())
UpdateFont(cooldown) UpdateFont(cooldown, (cooldown:GetParent() or cooldown):GetHeight())
end end
-- runs as a pfUI cooldown's timer starts: a timer with a total brings back -- runs as a pfUI cooldown's timer starts: a timer with a total brings back
-- the sweep a time-left-only one took away, and the font follows a changed -- the sweep a time-left-only one took away
-- height
local function StartTimer(cooldown, timeleftOnly) local function StartTimer(cooldown, timeleftOnly)
if cooldown.pfTimeLeftOnly ~= timeleftOnly then if cooldown.pfTimeLeftOnly ~= timeleftOnly then
cooldown.pfTimeLeftOnly = timeleftOnly cooldown.pfTimeLeftOnly = timeleftOnly
SetupCooldown(cooldown) SetupCooldown(cooldown)
elseif cooldown:GetParent():GetHeight() ~= cooldown.pfCountdownHeight then
UpdateFont(cooldown)
end end
end end
@@ -140,6 +140,7 @@ end)
function pfUI.api.CreateCooldown(parent, kind, name) function pfUI.api.CreateCooldown(parent, kind, name)
local cooldown = CreateFrame("Cooldown", name, parent, "CooldownFrameTemplate") local cooldown = CreateFrame("Cooldown", name, parent, "CooldownFrameTemplate")
cooldown.pfCooldownKind = kind cooldown.pfCooldownKind = kind
cooldown:SetScript("OnSizeChanged", OnSizeChanged)
table.insert(cooldowns, cooldown) table.insert(cooldowns, cooldown)
SetupCooldown(cooldown) SetupCooldown(cooldown)
return cooldown return cooldown
+18 -8
View File
@@ -248,6 +248,11 @@ local VISIBILITY_EVENTS = {
UNIT_TARGET = true, -- a link of a chained frame's unit retargeted UNIT_TARGET = true, -- a link of a chained frame's unit retargeted
} }
-- The units of a chain that unit events name by token, whatever nampower does
-- with its GUID events: the focus, and the focus's target, whose unit events
-- ClassicAPI fires as "focustarget" from the unit's own fields.
local CHAIN_TOKENS = { focus = true, focustarget = true }
-- The events a frame hears hidden or not: the visibility events that concern -- The events a frame hears hidden or not: the visibility events that concern
-- the unit it was created for (raid.lua remaps a raid frame's label, so this is -- the unit it was created for (raid.lua remaps a raid frame's label, so this is
-- decided once, at creation), and the logout guard. UNIT_TARGET belongs to -- decided once, at creation), and the logout guard. UNIT_TARGET belongs to
@@ -482,7 +487,9 @@ function pfUI.uf:UpdateVisibility()
-- --
-- A chained unit -- another unit's target, "targettarget" or "party1target" -- A chained unit -- another unit's target, "targettarget" or "party1target"
-- -- has no token that unit events name, so the frame follows it by GUID, -- -- has no token that unit events name, so the frame follows it by GUID,
-- which every unit event also fires with. It follows the unit only while -- which nampower fires every unit event with too, unless its GUID events
-- are off or filtered. The focus's target is named (CHAIN_TOKENS), so that
-- frame follows its token instead. It follows the unit only while
-- the client has it: a link's target can be out of sight, and its coming -- the client has it: a link's target can be out of sight, and its coming
-- back is then a new unit too. The unit changes with no event of its own -- back is then a new unit too. The unit changes with no event of its own
-- whenever a link of the chain retargets; UNIT_TARGET on every link reports -- whenever a link of the chain retargets; UNIT_TARGET on every link reports
@@ -491,8 +498,9 @@ function pfUI.uf:UpdateVisibility()
self.chain = visibility ~= "hide" and unitstr:match("^(.+)target$") or nil self.chain = visibility ~= "hide" and unitstr:match("^(.+)target$") or nil
if self.chain then if self.chain then
local guid = UnitName(unitstr) and UnitGUID(unitstr) local guid = UnitName(unitstr) and UnitGUID(unitstr)
if guid ~= self.eventunit then self.update_full = true end if guid ~= self.unitguid then self.update_full = true end
self:RegisterUnitEvents(guid) self.unitguid = guid
self:RegisterUnitEvents(guid and CHAIN_TOKENS[unitstr] and unitstr or guid)
else else
self:RegisterUnitEvents(visibility ~= "hide" and unitstr or nil) self:RegisterUnitEvents(visibility ~= "hide" and unitstr or nil)
end end
@@ -1359,8 +1367,8 @@ local UNIT_EVENTS = {
-- Auras and power. ClassicAPI's UNIT_AURA_DELTA also reports refreshes and new -- Auras and power. ClassicAPI's UNIT_AURA_DELTA also reports refreshes and new
-- durations and says what changed; its generic power events name the power, so -- durations and says what changed; its generic power events name the power, so
-- a frame skips the ones it does not draw. Both fire for tokens only, so a -- a frame skips the ones it does not draw. Both fire for tokens only, and not
-- chained unit, followed by GUID, keeps 1.12's events instead. A group -- as "focustarget", so a chained unit keeps 1.12's events instead. A group
-- member's connection and sight come with them, and a chained unit has -- member's connection and sight come with them, and a chained unit has
-- neither event. -- neither event.
local TOKEN_EVENTS = { local TOKEN_EVENTS = {
@@ -1425,16 +1433,18 @@ end
-- unit, whose `owner` is the unit it is the target of -- for -- unit, whose `owner` is the unit it is the target of -- for
-- "targettargettarget" the links are "targettarget" and "target" -- or drop it -- "targettargettarget" the links are "targettarget" and "target" -- or drop it
-- when `owner` is nil. By GUID, since the inner links are no token that events -- when `owner` is nil. By GUID, since the inner links are no token that events
-- name. Cheap to call repeatedly: it re-registers only when a link changed. -- name, save the ones in CHAIN_TOKENS. Cheap to call repeatedly: it
-- re-registers only when a link changed.
local chainlinks = {} local chainlinks = {}
function pfUI.uf:RegisterChainEvents(owner) function pfUI.uf:RegisterChainEvents(owner)
local n, key = 0, nil local n, key = 0, nil
while owner do while owner do
local guid = UnitGUID(owner) local guid = UnitGUID(owner)
if guid then if guid then
local link = CHAIN_TOKENS[owner] and owner or guid
n = n + 1 n = n + 1
chainlinks[n] = guid chainlinks[n] = link
key = key and key .. guid or guid key = key and key .. link or link
end end
owner = owner:match("^(.+)target$") owner = owner:match("^(.+)target$")
end end
+4 -3
View File
@@ -17,9 +17,10 @@ pfUI:RegisterModule("focus", function ()
-- PLAYER_FOCUS_CHANGED drives immediate refresh on focus assign / clear. -- PLAYER_FOCUS_CHANGED drives immediate refresh on focus assign / clear.
-- Between events, ClassicAPI fires UNIT_* (health/mana/aura/...) with -- Between events, ClassicAPI fires UNIT_* (health/mana/aura/...) with
-- arg1 == "focus", so the bars update event-driven like target. -- arg1 == "focus", so the bars update event-driven like target.
-- focustarget is a chained unit like targettarget: UNIT_TARGET follows the -- focustarget is a chained unit like targettarget, but ClassicAPI fires its
-- focus retargeting, and a new focus only needs its visibility re-checked, -- UNIT_* as "focustarget", and UNIT_TARGET on "focus" follows the focus
-- which queues the full refresh when its target is a different unit. -- retargeting. A new focus only needs its visibility re-checked, which
-- queues the full refresh when its target is a different unit.
pfUI.events:RegisterFrameEventAndCallback("PLAYER_FOCUS_CHANGED", function() pfUI.events:RegisterFrameEventAndCallback("PLAYER_FOCUS_CHANGED", function()
pfUI.uf:RefreshUnit(pfUI.uf.focus, "all") pfUI.uf:RefreshUnit(pfUI.uf.focus, "all")
pfUI.uf.focustarget:UpdateVisibility() pfUI.uf.focustarget:UpdateVisibility()
+22 -9
View File
@@ -671,7 +671,8 @@ pfUI:RegisterModule("nameplates", function ()
local function CreateDebuffIcon(plate, index) local function CreateDebuffIcon(plate, index)
local icon = CreateFrame("Frame", plate.platename.."Debuff"..index, plate) local icon = CreateFrame("Frame", plate.platename.."Debuff"..index, plate)
icon:Hide() icon:Hide()
icon:SetFrameLevel(4) -- relative: a raised target plate can grow icons too
icon:SetFrameLevel(plate.health:GetFrameLevel())
icon.icon = icon:CreateTexture(nil, "BACKGROUND") icon.icon = icon:CreateTexture(nil, "BACKGROUND")
icon.icon:SetColorTexture(.3,1,.8,1) icon.icon:SetColorTexture(.3,1,.8,1)
@@ -684,7 +685,7 @@ pfUI:RegisterModule("nameplates", function ()
icon.stacks:SetTextColor(1,1,0) icon.stacks:SetTextColor(1,1,0)
icon.cd = CreateCooldown(icon, "nameplate", plate.platename.."Debuff"..index.."Cooldown") icon.cd = CreateCooldown(icon, "nameplate", plate.platename.."Debuff"..index.."Cooldown")
icon.cd:SetFrameLevel(6) icon.cd:SetFrameLevel(icon:GetFrameLevel() + 2)
plate.debuffs[index] = icon plate.debuffs[index] = icon
end end
@@ -799,11 +800,22 @@ pfUI:RegisterModule("nameplates", function ()
plate:SetAlpha(alpha) plate:SetAlpha(alpha)
end end
local function UpdateStrata(plate) -- The engine's plates draw in the world frame's stratum, under every UI
local strata = plate.istarget and "LOW" or "BACKGROUND" -- stratum, and the overlay inherits it; a SetFrameStrata would lift it into
if plate.strata == strata then return end -- the UI's and over the chat. The target rises above the other plates by
plate.strata = strata -- level instead: raise the engine frame, then re-parent the overlay, which
plate:SetFrameStrata(strata) -- moves its whole subtree to the new parent level.
local TARGET_RAISE = 20
local function UpdateStacking(plate)
local raised = plate.istarget and true or nil
if plate.raised == raised then return end
plate.raised = raised
local parent = plate.parent
parent:SetFrameLevel(plate.baselevel + (raised and TARGET_RAISE or 0))
-- SetParent does nothing for the same parent, so it goes through nil
plate:SetParent(nil)
plate:SetParent(parent)
end end
-- ============================================================================ -- ============================================================================
@@ -957,7 +969,7 @@ pfUI:RegisterModule("nameplates", function ()
-- ============================================================================ -- ============================================================================
local function SetTarget(plate, istarget) local function SetTarget(plate, istarget)
plate.istarget = istarget plate.istarget = istarget
UpdateStrata(plate) UpdateStacking(plate)
UpdateBorder(plate) UpdateBorder(plate)
UpdateLayout(plate) UpdateLayout(plate)
UpdateCombo(plate) UpdateCombo(plate)
@@ -1028,7 +1040,7 @@ pfUI:RegisterModule("nameplates", function ()
UpdateLayout(plate) UpdateLayout(plate)
UpdateDebuffs(plate) UpdateDebuffs(plate)
UpdateCombo(plate) UpdateCombo(plate)
UpdateStrata(plate) UpdateStacking(plate)
UpdateAlpha(plate) UpdateAlpha(plate)
UpdateCast(plate) UpdateCast(plate)
if cfg.targetzoom and plate.istarget then StartZoom(plate, true) end if cfg.targetzoom and plate.istarget then StartZoom(plate, true) end
@@ -1160,6 +1172,7 @@ pfUI:RegisterModule("nameplates", function ()
nameplate.platename = platename nameplate.platename = platename
nameplate:EnableMouse(false) nameplate:EnableMouse(false)
nameplate.parent = parent nameplate.parent = parent
nameplate.baselevel = parent:GetFrameLevel()
nameplate.cache = {} nameplate.cache = {}
-- Each plate watches its own unit. With RegisterUnitEvent the token IS the -- Each plate watches its own unit. With RegisterUnitEvent the token IS the