mirror of
https://github.com/brues-code/pfUI.git
synced 2026-11-02 17:06:57 +00:00
Show cooldown text through ClassicAPI's native countdown
The cooldown module no longer builds its own text frame with a 10 Hz OnUpdate per cooldown. The CooldownFrame_SetTimer hook now configures each Cooldown frame's own countdown instead: SetHideCountdownNumbers for the per-frame text toggles and omnicc's noCooldownCount, SetMinimumCountdownDuration for the GCD threshold, and GetCountdownFontString for the pfUI font and size. The engine ticks the numbers, gated by the countdownForCooldowns cvar. The cvar gets a checkbox in the Cooldown settings, and pfUI.SetupCVars turns it on. The text comes from one shared C_StringUtil numeric rule formatter, given to each frame with SetCountdownFormatter. Its breakpoints keep pfUI's format: the number in its unit's cooldown color, a unit (m/h/d) once the unit below passes 99, and tenths in the low color when milliseconds are on. Values now round up. GetColoredTimeString formats through the same formatter, so the buff, buffwatch and tooltip timers match. A config:changed callback rebuilds the breakpoints, and every frame picks them up on its next update. The paper-doll slots swap their indicator Models for Cooldown frames, as the spellbook and bags already do. They and the spellbook take the BLIZZARD tag when they are created, replacing the per-update hooks in the skin module. Models get no numbers. Hide Foreign Cooldown Animations clears the draw flags instead of setting alpha to 0, so the numbers stay visible. The buff module's sweep hides its numbers because buff.timer carries the text.
This commit is contained in:
+3
-2
@@ -130,7 +130,7 @@ pfUI:RegisterModule("buff", function ()
|
||||
|
||||
-- overlay lifts the texts above the sweep: a child frame renders above
|
||||
-- all of its parent's own regions, so the timer would dim under the
|
||||
-- dark wedge otherwise (same reason pfCooldownText is its own frame)
|
||||
-- dark wedge otherwise
|
||||
buff.overlay = CreateFrame("Frame", nil, buff)
|
||||
buff.overlay:SetAllPoints(buff)
|
||||
|
||||
@@ -148,8 +148,9 @@ pfUI:RegisterModule("buff", function ()
|
||||
-- radial sweep (the template covers the button and starts hidden).
|
||||
-- RefreshBuffButton drives it through the frame's own methods, never
|
||||
-- CooldownFrame_SetTimer, so the cooldown module's hook leaves it alone;
|
||||
-- text stays with buff.timer
|
||||
-- text stays with buff.timer, so the frame's own numbers are hidden
|
||||
buff.cd = CreateFrame("Cooldown", buttonName .. "Cooldown", buff, "CooldownFrameTemplate")
|
||||
buff.cd:SetHideCountdownNumbers(true)
|
||||
buff.cd:SetFrameLevel(buff:GetFrameLevel() + 1)
|
||||
buff.overlay:SetFrameLevel(buff:GetFrameLevel() + 2)
|
||||
|
||||
|
||||
+34
-123
@@ -1,71 +1,17 @@
|
||||
pfUI:RegisterModule("cooldown", function ()
|
||||
-- cache values
|
||||
-- local lowcolor = {strsplit(",", C.appearance.cd.lowcolor)}
|
||||
-- local normalcolor = {strsplit(",", C.appearance.cd.normalcolor)}
|
||||
-- local minutecolor = {strsplit(",", C.appearance.cd.minutecolor)}
|
||||
-- local hourcolor = {strsplit(",", C.appearance.cd.hourcolor)}
|
||||
-- local daycolor = {strsplit(",", C.appearance.cd.daycolor)}
|
||||
|
||||
local function pfCooldownOnUpdate()
|
||||
-- Throttle FIRST. One of these runs per visible cooldown text, every frame,
|
||||
-- so anything above this gate is multiplied by the frame rate and by how
|
||||
-- many cooldowns are ticking.
|
||||
local now = GetTime()
|
||||
if (this.tick or 0) > now then return end
|
||||
this.tick = now + .1
|
||||
|
||||
local parent = this:GetParent()
|
||||
if not parent then this:Hide() return end
|
||||
|
||||
-- avoid to set cooldowns on invalid frames. The cooldown frame is stashed
|
||||
-- at creation: resolving it as _G[parent:GetName() .. "Cooldown"] built and
|
||||
-- interned that string twice per call, and this is the hottest path in the
|
||||
-- UI. The stashed reference is also the frame itself rather than a guess
|
||||
-- from its parent's name, so it holds for cooldowns named anything else.
|
||||
if this.cooldown and not this.cooldown:IsShown() then
|
||||
this:Hide()
|
||||
return
|
||||
end
|
||||
|
||||
-- fix own alpha value (should be inherited, but somehow isn't always)
|
||||
if this:GetAlpha() ~= parent:GetAlpha() then
|
||||
this:SetAlpha(parent:GetAlpha())
|
||||
end
|
||||
|
||||
if this.start < now then
|
||||
-- calculating remaining time as it should be
|
||||
local remaining = this.duration - (now - this.start)
|
||||
if remaining >= 0 then
|
||||
this.text:SetText(GetColoredTimeString(remaining))
|
||||
else
|
||||
this:Hide()
|
||||
end
|
||||
else
|
||||
-- I have absolutely no idea, but it works:
|
||||
-- https://github.com/Stanzilla/WoWUIBugs/issues/47
|
||||
local currentTime = time()
|
||||
local startupTime = currentTime - now
|
||||
-- just a simplification of: ((2^32) - (start * 1000)) / 1000
|
||||
local cdTime = (2 ^ 32) / 1000 - this.start
|
||||
local cdStartTime = startupTime - cdTime
|
||||
local cdEndTime = cdStartTime + this.duration
|
||||
local remaining = cdEndTime - currentTime
|
||||
|
||||
if remaining >= 0 then
|
||||
this.text:SetText(GetColoredTimeString(remaining))
|
||||
else
|
||||
this:Hide()
|
||||
end
|
||||
end
|
||||
end
|
||||
-- The numbers are the Cooldown frame's own countdown (ClassicAPI): the
|
||||
-- engine ticks them, gated by the countdownForCooldowns cvar, and writes
|
||||
-- them through pfUI's shared formatter. pfUI only configures each frame as
|
||||
-- its timer is set.
|
||||
|
||||
local function GetCooldownHeight(cooldown)
|
||||
return cooldown:GetParent() and cooldown:GetParent():GetHeight() or cooldown:GetHeight() or 0
|
||||
end
|
||||
|
||||
-- sizes the text to the cooldown's current height; the dynamic size follows
|
||||
-- the frame, so SetCooldown calls this again whenever that height changes
|
||||
local function pfUpdateCooldownFont(cooldown)
|
||||
-- sizes the numbers to the cooldown's current height; the dynamic size
|
||||
-- follows the frame, so SetCooldown calls this again whenever that height
|
||||
-- changes
|
||||
local function UpdateCountdownFont(cooldown)
|
||||
local size
|
||||
if not cooldown.pfCooldownType then
|
||||
size = tonumber(C.appearance.cd.font_size_foreign)
|
||||
@@ -77,88 +23,53 @@ pfUI:RegisterModule("cooldown", function ()
|
||||
size = tonumber(C.appearance.cd.font_size)
|
||||
end
|
||||
|
||||
local height = GetCooldownHeight(cooldown)
|
||||
cooldown.pfCountdownHeight = height
|
||||
|
||||
-- enforce dynamic font size
|
||||
if C.appearance.cd.dynamicsize == "1" then
|
||||
local height = GetCooldownHeight(cooldown)
|
||||
cooldown.pfCooldownText.height = height
|
||||
size = math.max((height > 0 and height * .64 or 16), size)
|
||||
end
|
||||
|
||||
cooldown.pfCooldownText.text:SetFont(pfUI.media[C.appearance.cd.font], size, "OUTLINE")
|
||||
end
|
||||
|
||||
local textcount = 0
|
||||
local function pfCreateCoolDown(cooldown, start, duration)
|
||||
textcount = textcount + 1
|
||||
local name = cooldown.GetName and cooldown:GetName() or "pfCooldown" .. textcount
|
||||
|
||||
cooldown.pfCooldownText = CreateFrame("Frame", name .. "Text", cooldown:GetParent())
|
||||
cooldown.pfCooldownText.cooldown = cooldown
|
||||
cooldown.pfCooldownText:SetAllPoints(cooldown)
|
||||
cooldown.pfCooldownText:SetFrameLevel(cooldown:GetParent():GetFrameLevel() + 2)
|
||||
cooldown.pfCooldownText.text = cooldown.pfCooldownText:CreateFontString(name .. "TextString", "OVERLAY")
|
||||
|
||||
pfUpdateCooldownFont(cooldown)
|
||||
cooldown.pfCooldownText.text:SetPoint("CENTER", cooldown.pfCooldownText, "CENTER", 0, 0)
|
||||
cooldown.pfCooldownText:SetScript("OnUpdate", pfCooldownOnUpdate)
|
||||
cooldown:GetCountdownFontString():SetFont(pfUI.media[C.appearance.cd.font], size, "OUTLINE")
|
||||
end
|
||||
|
||||
-- hook
|
||||
local function SetCooldown(this, start, duration, enable)
|
||||
-- abort on unknown frames
|
||||
if C.appearance.cd.foreign == "0" and not this.pfCooldownType then
|
||||
local function SetCooldown(this)
|
||||
-- 1.12's indicator Models have no countdown and keep the stock timer
|
||||
if not this:IsObjectType("Cooldown") then return end
|
||||
|
||||
-- no numbers on unknown frames, nor on frames with omnicc's disable flag
|
||||
if (C.appearance.cd.foreign == "0" and not this.pfCooldownType) or this.noCooldownCount then
|
||||
this:SetHideCountdownNumbers(true)
|
||||
return
|
||||
end
|
||||
|
||||
-- add support for omnicc's disable flag
|
||||
if this.noCooldownCount then
|
||||
return
|
||||
this:SetHideCountdownNumbers(this.pfCooldownStyleText == 0)
|
||||
|
||||
-- no numbers for global cooldowns, except on frames that time auras
|
||||
if not this.pfCooldownType or this.pfCooldownType == "NOGCD" then
|
||||
this:SetMinimumCountdownDuration(tonumber(C.appearance.cd.threshold) * 1000)
|
||||
else
|
||||
this:SetMinimumCountdownDuration(0)
|
||||
end
|
||||
|
||||
-- realign the indicator Models that stock buttons build; the model is
|
||||
-- drawn at 36px and needs scaling to its button. A Cooldown draws its
|
||||
-- sweep to its own rect.
|
||||
local parent = this.GetParent and not this:IsObjectType("Cooldown") and this:GetParent()
|
||||
if parent and parent:GetWidth() / 36 > 0 then
|
||||
this:SetScale(parent:GetWidth() / 36)
|
||||
this:SetPoint("TOPLEFT", parent, "TOPLEFT", -1, 1)
|
||||
this:SetPoint("BOTTOMRIGHT", parent, "BOTTOMRIGHT", 1, -1)
|
||||
end
|
||||
|
||||
-- don't draw global cooldowns
|
||||
if this.pfCooldownType == "NOGCD" and duration < tonumber(C.appearance.cd.threshold) then
|
||||
start, duration = 0, 0
|
||||
end
|
||||
|
||||
-- disable GCDs on non pfUI frames
|
||||
if not this.pfCooldownType and duration < tonumber(C.appearance.cd.threshold) then
|
||||
start, duration = 0, 0
|
||||
end
|
||||
this:SetCountdownFormatter(GetCountdownFormatter())
|
||||
|
||||
-- hide foreign animations; frames that set pfCooldownStyleAnimation
|
||||
-- configure their own sweep (SetDrawSwipe, SetReverse)
|
||||
-- configure their own sweep. The draw flags, not alpha, so the numbers
|
||||
-- stay visible
|
||||
if not this.pfCooldownStyleAnimation and C.appearance.cd.hideanim == "1" then
|
||||
this:SetAlpha(0)
|
||||
this:SetDrawSwipe(false)
|
||||
this:SetDrawBling(false)
|
||||
end
|
||||
|
||||
-- print time as text on cooldown frames
|
||||
if ( not this.pfCooldownStyleText or this.pfCooldownStyleText == 1)
|
||||
and start > 0 and duration > 0 and (not enable or enable > 0) then
|
||||
if( not this.pfCooldownText ) then
|
||||
pfCreateCoolDown(this, start, duration)
|
||||
elseif C.appearance.cd.dynamicsize == "1" and GetCooldownHeight(this) ~= this.pfCooldownText.height then
|
||||
pfUpdateCooldownFont(this)
|
||||
end
|
||||
|
||||
this.pfCooldownText.start = start
|
||||
this.pfCooldownText.duration = duration
|
||||
this.pfCooldownText:Show()
|
||||
elseif(this.pfCooldownText) then
|
||||
this.pfCooldownText:Hide()
|
||||
if GetCooldownHeight(this) ~= this.pfCountdownHeight then
|
||||
UpdateCountdownFont(this)
|
||||
end
|
||||
end
|
||||
|
||||
-- hook the SetTimer function that every cooldown, Cooldown frame or
|
||||
-- stock indicator Model, is driven through.
|
||||
hooksecurefunc("CooldownFrame_SetTimer", SetCooldown)
|
||||
end)
|
||||
end)
|
||||
|
||||
@@ -1597,6 +1597,7 @@ pfUI:RegisterModule("gui", function ()
|
||||
end)
|
||||
|
||||
CreateGUIEntry(T["Settings"], T["Cooldown"], function()
|
||||
CreateConfig(nil, COUNTDOWN_FOR_COOLDOWNS_TEXT, "CVAR", "countdownForCooldowns", "checkbox")
|
||||
CreateConfig(U["buff"], T["Show Milliseconds When Timer Runs Out"], C.appearance.cd, "milliseconds", "checkbox")
|
||||
CreateConfig(nil, T["Cooldown Color (Less than 3 Sec)"], C.appearance.cd, "lowcolor", "color")
|
||||
CreateConfig(nil, T["Cooldown Color (Seconds)"], C.appearance.cd, "normalcolor", "color")
|
||||
|
||||
@@ -15,18 +15,6 @@ pfUI:RegisterModule("skin", function ()
|
||||
DurabilityFrame:SetFrameLevel(1)
|
||||
DurabilityFrame.SetPoint = function() return end
|
||||
|
||||
if C.appearance.cd.blizzard == "1" then
|
||||
hooksecurefunc("PaperDollItemSlotButton_Update", function()
|
||||
local cooldown = _G[this:GetName().."Cooldown"]
|
||||
if cooldown then cooldown.pfCooldownType = "BLIZZARD" end
|
||||
end)
|
||||
|
||||
hooksecurefunc("SpellButton_UpdateButton", function()
|
||||
local cooldown = _G[this:GetName().."Cooldown"]
|
||||
if cooldown then cooldown.pfCooldownType = "BLIZZARD" end
|
||||
end)
|
||||
end
|
||||
|
||||
for i = 1, UIDROPDOWNMENU_MAXLEVELS do
|
||||
CreateBackdrop(_G["DropDownList"..i.."MenuBackdrop"], nil, true, .8)
|
||||
CreateBackdropShadow(_G["DropDownList"..i.."MenuBackdrop"])
|
||||
|
||||
Reference in New Issue
Block a user