This repository has been archived by the owner on Jan 28, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathdisplay.lua
277 lines (211 loc) · 6.71 KB
/
display.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
-- A cooldown text display
local _, Addon = ...
-- the expected size of an icon
local ICON_SIZE = 36
local After = C_Timer.After
local GetTickTime = GetTickTime
local min = math.min
local round = Round
local UIParent = UIParent
local displays = {}
local Display = CreateFrame("Frame")
Display:Hide()
Display.__index = Display
function Display:Get(owner)
return displays[owner]
end
function Display:GetOrCreate(owner)
if not owner then return end
return displays[owner] or self:Create(owner)
end
function Display:Create(owner)
local display = setmetatable(CreateFrame("Frame", nil, owner), Display)
display:Hide()
display:SetScript("OnSizeChanged", self.OnSizeChanged)
display.text = display:CreateFontString(nil, "OVERLAY")
display.text:SetFont(STANDARD_TEXT_FONT, 8, "THIN")
display.cooldowns = {}
display.updateScaleCallback = function() display:OnScaleChanged() end
display:UpdateCooldownTextShadow()
displays[owner] = display
return display
end
-- adjust font size whenever the timer's size changes
-- and hide if it gets too tiny
function Display:OnSizeChanged()
local oldSize = self.sizeRatio
if oldSize ~= self:CalculateSizeRatio() then
self:UpdateCooldownTextShown()
self:UpdateCooldownTextFont()
self:UpdateCooldownTextPosition()
end
end
-- adjust font size whenever the timer's size changes
-- and hide if it gets too tiny
function Display:OnScaleChanged()
local oldScale = self.scaleRatio
if oldScale ~= self:CalculateScaleRatio() then
self:UpdateCooldownTextShown()
end
end
-- update text when the timer notifies us of a change
function Display:OnTimerTextUpdated(timer, text)
if timer ~= self.timer then return end
self.text:SetText(text or "")
end
function Display:OnTimerStateUpdated(timer, state)
if timer ~= self.timer then return end
state = state or "seconds"
if self.state ~= state then
self.state = state
self:UpdateCooldownTextFont()
end
end
function Display:OnTimerDestroyed(timer)
if self.timer == timer then
self:RemoveCooldown(self.activeCooldown)
end
end
function Display:CalculateSizeRatio()
local sizeRatio
if Addon.Config.scaleText then
sizeRatio = round(min(self:GetSize())) / ICON_SIZE
else
sizeRatio = 1
end
self.sizeRatio = sizeRatio
return sizeRatio
end
function Display:CalculateScaleRatio()
local scaleRatio = self:GetEffectiveScale() / UIParent:GetEffectiveScale()
self.scaleRatio = scaleRatio
return scaleRatio
end
function Display:AddCooldown(cooldown)
local cooldowns = self.cooldowns
if not cooldowns[cooldown] then
cooldowns[cooldown] = true
end
self:UpdatePrimaryCooldown()
self:UpdateTimer()
end
function Display:RemoveCooldown(cooldown)
local cooldowns = self.cooldowns
if cooldowns[cooldown] then
cooldowns[cooldown] = nil
self:UpdatePrimaryCooldown()
self:UpdateTimer()
end
end
function Display:UpdatePrimaryCooldown()
local cooldown = self:GetCooldownWithHighestPriority()
if self.activeCooldown ~= cooldown then
self.activeCooldown = cooldown
if cooldown then
self:SetAllPoints(cooldown)
self:SetFrameLevel(cooldown:GetFrameLevel() + 7)
end
end
end
function Display:UpdateTimer()
local oldTimer = self.timer
local oldTimerKey = oldTimer and oldTimer.key
local newTimer = self.activeCooldown and Addon.Timer:GetOrCreate(self.activeCooldown)
local newTimerKey = newTimer and newTimer.key
-- update subscription if we're watching a different timer
if oldTimer ~= newTimer then
if oldTimer then
oldTimer:Unsubscribe(self)
end
self.timer = newTimer
end
-- only show display if we have a timer to watch
if newTimer then
newTimer:Subscribe(self)
-- only update text if the timer we're watching has changed
if newTimerKey ~= oldTimerKey then
self:OnTimerTextUpdated(newTimer, newTimer.text)
self:OnTimerStateUpdated(newTimer, newTimer.state)
self:Show()
end
-- SUF hack to update scale of frames after cooldowns are set
After(GetTickTime(), self.updateScaleCallback)
else
self:Hide()
end
end
do
-- given two cooldowns, returns the more important one
local function cooldown_Compare(lhs, rhs)
if lhs == rhs then
return lhs
end
-- prefer the one that isn't nil
if rhs == nil then
return lhs
end
if lhs == nil then
return rhs
end
-- prefer cooldowns ending first
local lEnd = lhs._tcc_start + lhs._tcc_duration
local rEnd = rhs._tcc_start + rhs._tcc_duration
if lEnd < rEnd then
return lhs
end
if lEnd > rEnd then
return rhs
end
-- then check priority
if lhs._tcc_priority < rhs._tcc_priority then
return lhs
end
return rhs
end
function Display:GetCooldownWithHighestPriority()
local result
for cooldown in pairs(self.cooldowns) do
result = cooldown_Compare(cooldown, result)
end
return result
end
end
function Display:UpdateCooldownTextShown()
local sizeRatio = self.sizeRatio or self:CalculateSizeRatio()
local scaleRatio = self.scaleRatio or self:CalculateScaleRatio()
if (sizeRatio * scaleRatio) >= (Addon.Config.minScale or 0) then
self.text:Show()
else
self.text:Hide()
end
end
function Display:UpdateCooldownTextFont()
local sets = Addon.Config
local style = sets.styles[self.state or "seconds"]
local fontSize = sets.fontSize * style.scale * (self.sizeRatio or self:CalculateSizeRatio())
if self.fontSize == fontSize then
return
end
self.fontSize = fontSize
if fontSize > 0 then
local text = self.text
if not text:SetFont(sets.fontFace, fontSize, sets.fontOutline) then
text:SetFont(STANDARD_TEXT_FONT, fontSize, sets.fontOutline)
end
text:SetTextColor(style.r, style.g, style.b, style.a)
end
end
function Display:UpdateCooldownTextShadow()
local fontShadow = Addon.Config.fontShadow
local text = self.text
text:SetShadowColor(fontShadow.r, fontShadow.g, fontShadow.b, fontShadow.a)
text:SetShadowOffset(fontShadow.x, fontShadow.y)
end
function Display:UpdateCooldownTextPosition()
local sets = Addon.Config
local sizeRatio = self.sizeRatio or self:CalculateSizeRatio()
self.text:ClearAllPoints()
self.text:SetPoint(sets.anchor, sets.xOff * sizeRatio, sets.yOff * sizeRatio)
end
-- exports
Addon.Display = Display