-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathtimebar.lua
582 lines (494 loc) · 19.3 KB
/
timebar.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
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
---@type detailsframework
local detailsFramework = _G["DetailsFramework"]
if (not detailsFramework or not DetailsFrameworkCanLoad) then
return
end
local _
local type = type
local floor = math.floor
local GetTime = GetTime
---@class df_timebar : statusbar, df_scripthookmixin, df_widgets
---@field type string
---@field dframework boolean
---@field statusBar df_timebar_statusbar
---@field widget statusbar
---@field direction string
---@field HookList table
---@field tooltip string
---@field locked boolean
---@field HasTimer fun(self:df_timebar):boolean return if the timer bar is active showing a timer
---@field SetTimer fun(self:df_timebar, currentTime:number, startTime:number|boolean|nil, endTime:number|nil)
---@field StartTimer fun(self:df_timebar, currentTime:number, startTime:number, endTime:number)
---@field StopTimer fun(self:df_timebar)
---@field ShowSpark fun(self:df_timebar, state:boolean, alpha:number|nil, color:string|nil)
---@field ShowTimer fun(self:df_timebar, bShowTimer:boolean)
---@field SetIcon fun(self:df_timebar, texture:string, L:number|nil, R:number|nil, T:number|nil, B:number|nil)
---@field SetIconSize fun(self:df_timebar, width:number, height:number)
---@field SetTexture fun(self:df_timebar, texture:texturepath|textureid)
---@field SetColor fun(self:df_timebar, color:any, green:number|nil, blue:number|nil, alpha:number|nil)
---@field SetLeftText fun(self:df_timebar, text:string)
---@field SetRightText fun(self:df_timebar, text:string)
---@field SetFont fun(self:df_timebar, font:string|nil, size:number|nil, color:any, outline:string|boolean|nil, shadowColor:any, shadowX:number?, shadowY:number?)
---@field SetThrottle fun(self:df_timebar, seconds:number)
---@field SetDirection fun(self:df_timebar, direction:string)
---@field SetBackgroundColor fun(self:df_timebar, color:any, green:number|nil, blue:number|nil, alpha:number|nil)
---@class df_timebar_statusbar : statusbar
---@field MyObject df_timebar
---@field hasTimer boolean
---@field startTime number
---@field endTime number
---@field timeLeft1 number
---@field timeLeft2 number
---@field throttle number
---@field isUsingThrottle boolean
---@field showTimer boolean
---@field amountThrottle number
---@field sparkAlpha number
---@field sparkColorR number
---@field sparkColorG number
---@field sparkColorB number
---@field dontShowSpark boolean
---@field direction string
---@field spark texture
---@field icon texture
---@field leftText fontstring
---@field rightText fontstring
---@field backgroundTexture texture
---@field barTexture texture
local APITimeBarFunctions
do
local metaPrototype = {
WidgetType = "timebar",
dversion = detailsFramework.dversion,
}
--check if there's a metaPrototype already existing
if (_G[detailsFramework.GlobalWidgetControlNames["timebar"]]) then
--get the already existing metaPrototype
local oldMetaPrototype = _G[detailsFramework.GlobalWidgetControlNames["timebar"]]
--check if is older
if ( (not oldMetaPrototype.dversion) or (oldMetaPrototype.dversion < detailsFramework.dversion) ) then
--the version is older them the currently loading one
--copy the new values into the old metatable
for funcName, _ in pairs(metaPrototype) do
oldMetaPrototype[funcName] = metaPrototype[funcName]
end
end
else
--first time loading the framework
_G[detailsFramework.GlobalWidgetControlNames["timebar"]] = metaPrototype
end
end
local TimeBarMetaFunctions = _G[detailsFramework.GlobalWidgetControlNames["timebar"]]
detailsFramework:Mixin(TimeBarMetaFunctions, detailsFramework.ScriptHookMixin)
--methods
TimeBarMetaFunctions.SetMembers = TimeBarMetaFunctions.SetMembers or {}
TimeBarMetaFunctions.GetMembers = TimeBarMetaFunctions.GetMembers or {}
TimeBarMetaFunctions.__index = function(table, key)
local func = TimeBarMetaFunctions.GetMembers[key]
if (func) then
return func(table, key)
end
local fromMe = rawget(table, key)
if (fromMe) then
return fromMe
end
return TimeBarMetaFunctions[key]
end
TimeBarMetaFunctions.__newindex = function(table, key, value)
local func = TimeBarMetaFunctions.SetMembers[key]
if (func) then
return func(table, value)
else
return rawset(table, key, value)
end
end
--scripts
local OnEnterFunc = function(statusBar)
local kill = statusBar.MyObject:RunHooksForWidget("OnEnter", statusBar, statusBar.MyObject)
if (kill) then
return
end
if (statusBar.MyObject.tooltip) then
GameCooltip2:Reset()
GameCooltip2:AddLine(statusBar.MyObject.tooltip)
GameCooltip2:ShowCooltip(statusBar, "tooltip")
end
end
local OnLeaveFunc = function(statusBar)
local kill = statusBar.MyObject:RunHooksForWidget("OnLeave", statusBar, statusBar.MyObject)
if (kill) then
return
end
if (statusBar.MyObject.tooltip) then
GameCooltip2:Hide()
end
end
local OnHideFunc = function(statusBar)
local kill = statusBar.MyObject:RunHooksForWidget("OnHide", statusBar, statusBar.MyObject)
if (kill) then
return
end
end
local OnShowFunc = function(statusBar)
local kill = statusBar.MyObject:RunHooksForWidget("OnShow", statusBar, statusBar.MyObject)
if (kill) then
return
end
end
local OnMouseDownFunc = function(statusBar, mouseButton)
local kill = statusBar.MyObject:RunHooksForWidget("OnMouseDown", statusBar, statusBar.MyObject)
if (kill) then
return
end
end
local OnMouseUpFunc = function(statusBar, mouseButton)
local kill = statusBar.MyObject:RunHooksForWidget("OnMouseUp", statusBar, statusBar.MyObject)
if (kill) then
return
end
end
--timer functions
function TimeBarMetaFunctions:SetIconSize(width, height)
if (width and not height) then
self.statusBar.icon:SetWidth(width)
elseif (not width and height) then
self.statusBar.icon:SetHeight(height)
elseif (width and height) then
self.statusBar.icon:SetSize(width, height)
end
end
function TimeBarMetaFunctions:SetIcon(texture, L, R, T, B)
if (texture) then
self.statusBar.icon:Show()
self.statusBar.icon:ClearAllPoints()
self.statusBar.icon:SetPoint("left", self.statusBar, "left", 2, 0)
self.statusBar.icon:SetSize(self.statusBar:GetHeight()-2, self.statusBar:GetHeight()-2)
self.statusBar.leftText:ClearAllPoints()
self.statusBar.leftText:SetPoint("left", self.statusBar.icon, "right", 2, 0)
self.statusBar.icon:SetTexture(texture)
if (L) then
self.statusBar.icon:SetTexCoord(L, R, T, B)
end
else
self.statusBar.icon:Hide()
self.statusBar.leftText:ClearAllPoints()
self.statusBar.leftText:SetPoint("left", self.statusBar, "left", 2, 0)
end
end
function TimeBarMetaFunctions:GetIcon()
return self.statusBar.icon
end
function TimeBarMetaFunctions:SetTexture(texture)
self.statusBar.barTexture:SetTexture(texture)
end
function TimeBarMetaFunctions:SetColor(color, green, blue, alpha)
local r, g, b, a = detailsFramework:ParseColors(color, green, blue, alpha)
self.statusBar.barTexture:SetVertexColor(r, g, b, a)
end
function TimeBarMetaFunctions:SetLeftText(text)
self.statusBar.leftText:SetText(text)
end
function TimeBarMetaFunctions:SetRightText(text)
self.statusBar.rightText:SetText(text)
end
function TimeBarMetaFunctions:SetFont(font, size, color, outline, shadowColor, shadowX, shadowY)
if (font) then
detailsFramework:SetFontFace(self.statusBar.leftText, font)
detailsFramework:SetFontFace(self.statusBar.rightText, font)
end
if (size) then
detailsFramework:SetFontSize(self.statusBar.leftText, size)
detailsFramework:SetFontSize(self.statusBar.rightText, size)
end
if (color) then
detailsFramework:SetFontColor(self.statusBar.leftText, color)
detailsFramework:SetFontColor(self.statusBar.rightText, color)
end
if (outline) then
detailsFramework:SetFontOutline(self.statusBar.leftText, outline)
detailsFramework:SetFontOutline(self.statusBar.rightText, outline)
end
if (shadowColor) then
self.statusBar.leftText:SetShadowColor(detailsFramework:ParseColors(shadowColor))
self.statusBar.rightText:SetShadowColor(detailsFramework:ParseColors(shadowColor))
end
if (shadowX and shadowY) then
self.statusBar.leftText:SetShadowOffset(shadowX, shadowY)
self.statusBar.rightText:SetShadowOffset(shadowX, shadowY)
end
end
--set background texture color
function TimeBarMetaFunctions:SetBackgroundColor(color, green, blue, alpha)
local r, g, b, a = detailsFramework:ParseColors(color, green, blue, alpha)
self.statusBar.backgroundTexture:SetVertexColor(r, g, b, a)
end
---set a throttle for the timer bar, the timer will only update every X seconds
---calling without parameters will disable the throttle
---@param seconds number|nil the amount of seconds to throttle the timer
function TimeBarMetaFunctions:SetThrottle(seconds)
if (seconds and seconds > 0) then
self.statusBar.isUsingThrottle = true
self.statusBar.amountThrottle = seconds
else
self.statusBar.isUsingThrottle = false
end
end
---accept 'left' 'right' or nil, if ommited will default to right
---@param direction "left"|"right"|nil the direction of the timer bar
function TimeBarMetaFunctions:SetDirection(direction)
direction = direction or "right"
self.direction = direction
end
function TimeBarMetaFunctions:HasTimer()
return self.statusBar.hasTimer
end
function TimeBarMetaFunctions:StopTimer()
if (self.statusBar.hasTimer) then
self.statusBar.hasTimer = nil
local kill = self:RunHooksForWidget("OnTimerEnd", self.statusBar, self)
if (kill) then
return
end
end
local statusBar = self.statusBar
statusBar:SetScript("OnUpdate", nil)
statusBar:SetMinMaxValues(0, 100)
statusBar:SetValue(100)
statusBar.rightText:SetText("")
statusBar.spark:Hide()
end
function TimeBarMetaFunctions:ShowTimer(bShowTimer)
if (bShowTimer) then
self.statusBar.showTimer = true
else
self.statusBar.showTimer = nil
end
end
function TimeBarMetaFunctions:ShowSpark(state, alpha, color)
if (type(state) == "boolean" and state == false) then
self.statusBar.dontShowSpark = true
else
self.statusBar.dontShowSpark = nil
end
if (alpha) then
self.statusBar.sparkAlpha = alpha
else
self.statusBar.sparkAlpha = nil
end
if (color) then
local r, g, b = detailsFramework:ParseColors(color)
if (r and g and b) then
self.statusBar.sparkColorR = r
self.statusBar.sparkColorG = g
self.statusBar.sparkColorB = b
end
else
self.statusBar.sparkColorR = nil
self.statusBar.sparkColorG = nil
self.statusBar.sparkColorB = nil
end
end
---@param self df_timebar_statusbar
---@param deltaTime number
local OnUpdateFunc = function(self, deltaTime)
if (self.isUsingThrottle) then
self.throttle = self.throttle + deltaTime
if (self.throttle < self.amountThrottle) then
return
end
self.throttle = 0
end
local timeNow = GetTime()
self:SetValue(timeNow)
--adjust the spark
local spark = self.spark
local startTime, endTime = self:GetMinMaxValues()
if (not self.dontShowSpark) then
if (endTime - startTime > 0) then
local pct = abs((timeNow - endTime) / (endTime - startTime))
pct = abs(1 - pct)
local sparkOffset = -16
if (self.direction ~= "right") then
--moving from right to left, so invert the pct
pct = abs(1 - pct)
sparkOffset = -14
end
spark:SetPoint("left", self, "left", (self:GetWidth() * pct) + sparkOffset, 0)
spark:Show()
else
spark:Hide()
end
end
if (self.showTimer) then
local timeLeft = floor(endTime - timeNow) + 1
local formatedTimeLeft = detailsFramework:IntegerToTimer(timeLeft)
self.rightText:SetText(formatedTimeLeft)
end
--check if finished
if (timeNow >= self.endTime) then
self.MyObject:StopTimer()
end
self.MyObject:RunHooksForWidget("OnUpdate", self, self, deltaTime)
end
---start a timer on the timebar
---calling without parameters will stop the timer
---@param self df_timebar
---@param currentTime number the time in seconds if startTime is a boolean true. GetTime() when start and end time are passed
---@param startTime number|boolean|nil GetTime() when the timer started. if passed true: startTime and endTime are GetTime() and GetTime() + currentTime, currenTime is the time in seconds
---@param endTime number|nil GetTime() when the timer will end. ignored if startTime is a boolean true
function TimeBarMetaFunctions:SetTimer(currentTime, startTime, endTime)
self.statusBar:Show()
if (not currentTime or currentTime == 0) then
self:StopTimer()
return
end
if (startTime and endTime) then
if (self.statusBar.hasTimer and currentTime == self.statusBar.timeLeft1) then
--it is the same timer called again
return
end
self.statusBar.startTime = tonumber(startTime) or 0 --fit the number type
self.statusBar.endTime = endTime
else
local bForceNewTimer = type(startTime) == "boolean" and startTime
if (self.statusBar.hasTimer and currentTime == self.statusBar.timeLeft2 and not bForceNewTimer) then
--it is the same timer called again
return
end
self.statusBar.startTime = GetTime()
self.statusBar.endTime = GetTime() + currentTime
self.statusBar.timeLeft2 = currentTime
end
self.statusBar:SetMinMaxValues(self.statusBar.startTime, self.statusBar.endTime)
if (self.direction == "right") then
self.statusBar:SetReverseFill(false)
else
self.statusBar:SetReverseFill(true)
end
if (self.statusBar.dontShowSpark) then
self.statusBar.spark:Hide()
else
self.statusBar.spark:Show()
self.statusBar.spark:SetHeight(self.statusBar:GetHeight()+26)
if (self.statusBar.sparkAlpha) then
self.statusBar.spark:SetAlpha(self.statusBar.sparkAlpha)
else
self.statusBar.spark:SetAlpha(1)
end
if (self.statusBar.sparkColorR) then
self.statusBar.spark:SetVertexColor(self.statusBar.sparkColorR, self.statusBar.sparkColorG, self.statusBar.sparkColorB)
else
self.statusBar.spark:SetVertexColor(1, 1, 1)
end
end
self.statusBar.hasTimer = true
self.statusBar.direction = self.direction
self.statusBar.throttle = 0
self.statusBar:SetScript("OnUpdate", OnUpdateFunc)
local kill = self:RunHooksForWidget("OnTimerStart", self.statusBar, self)
if (kill) then
return
end
end
---create a time bar widget, a timebar is a statubar that can have a timer and a spark
---@param parent frame the parent frame
---@param texture texturepath|textureid the texture of the bar
---@param width number? the width of the bar, default is 150
---@param height number? the height of the bar, default is 20
---@param value number? the initial value of the bar, default is 0
---@param member string? the name of the member in the parent frame
---@param name string? the name of the widget
---@return df_timebar
function detailsFramework:CreateTimeBar(parent, texture, width, height, value, member, name)
if (not name) then
name = "DetailsFrameworkBarNumber" .. detailsFramework.BarNameCounter
detailsFramework.BarNameCounter = detailsFramework.BarNameCounter + 1
elseif (not parent) then
error("Details! FrameWork: parent not found.", 2)
end
if (name:find("$parent")) then
local parentName = detailsFramework:GetParentName(parent)
name = name:gsub("$parent", parentName)
end
local timeBar = {
type = "timebar",
dframework = true
}
if (member) then
parent[member] = timeBar
end
---@diagnostic disable-next-line: undefined-field
if (parent.dframework) then
---@diagnostic disable-next-line: undefined-field
parent = parent.widget
end
value = value or 0
width = width or 150
height = height or 20
timeBar.locked = false
timeBar.statusBar = CreateFrame("statusbar", name, parent, "BackdropTemplate")
timeBar.widget = timeBar.statusBar
detailsFramework:Mixin(timeBar.statusBar, detailsFramework.WidgetFunctions)
timeBar.statusBar.MyObject = timeBar
timeBar.direction = "right"
if (not APITimeBarFunctions) then
APITimeBarFunctions = true
local idx = getmetatable(timeBar.statusBar).__index
for funcName, funcAddress in pairs(idx) do
if (not TimeBarMetaFunctions[funcName]) then
TimeBarMetaFunctions[funcName] = function(object, ...)
local x = loadstring("return _G['"..object.statusBar:GetName().."']:"..funcName.."(...)")
if (x) then
return x(...)
end
end
end
end
end
--create widgets
timeBar.statusBar:SetWidth(width)
timeBar.statusBar:SetHeight(height)
timeBar.statusBar:SetFrameLevel(parent:GetFrameLevel()+1)
timeBar.statusBar:SetMinMaxValues(0, 100)
timeBar.statusBar:SetValue(value or 100)
timeBar.statusBar:EnableMouse(false)
timeBar.statusBar.backgroundTexture = timeBar.statusBar:CreateTexture(nil, "border")
timeBar.statusBar.backgroundTexture:SetColorTexture(.9, .9, .9, 1)
timeBar.statusBar.backgroundTexture:SetVertexColor(.1, .1, .1, .6)
timeBar.statusBar.backgroundTexture:SetAllPoints()
timeBar.statusBar.barTexture = timeBar.statusBar:CreateTexture(nil, "artwork")
timeBar.statusBar.barTexture:SetTexture(texture or [[Interface\WorldStateFrame\WORLDSTATEFINALSCORE-HIGHLIGHT]])
timeBar.statusBar:SetStatusBarTexture(timeBar.statusBar.barTexture)
timeBar.statusBar.spark = timeBar.statusBar:CreateTexture(nil, "overlay", nil, 7)
timeBar.statusBar.spark:SetTexture([[Interface\CastingBar\UI-CastingBar-Spark]])
timeBar.statusBar.spark:SetBlendMode("ADD")
timeBar.statusBar.spark:Hide()
timeBar.statusBar.icon = timeBar.statusBar:CreateTexture(nil, "overlay", nil, 5)
timeBar.statusBar.icon:SetPoint("left", timeBar.statusBar, "left", 2, 0)
timeBar.statusBar.leftText = timeBar.statusBar:CreateFontString("$parentLeftText", "overlay", "GameFontNormal", 4)
timeBar.statusBar.leftText:SetPoint("left", timeBar.statusBar.icon, "right", 2, 0)
timeBar.statusBar.rightText = timeBar.statusBar:CreateFontString(nil, "overlay", "GameFontNormal", 4)
timeBar.statusBar.rightText:SetPoint("right", timeBar.statusBar, "right", -2, 0)
timeBar.statusBar.rightText:SetJustifyH("left")
--hooks
timeBar.HookList = {
OnEnter = {},
OnLeave = {},
OnHide = {},
OnShow = {},
OnUpdate = {},
OnMouseDown = {},
OnMouseUp = {},
OnTimerStart = {},
OnTimerEnd = {},
}
timeBar.statusBar:SetScript("OnEnter", OnEnterFunc)
timeBar.statusBar:SetScript("OnLeave", OnLeaveFunc)
timeBar.statusBar:SetScript("OnHide", OnHideFunc)
timeBar.statusBar:SetScript("OnShow", OnShowFunc)
timeBar.statusBar:SetScript("OnMouseDown", OnMouseDownFunc)
timeBar.statusBar:SetScript("OnMouseUp", OnMouseUpFunc)
--set class
setmetatable(timeBar, TimeBarMetaFunctions)
return timeBar
end