· 6 years ago · Mar 20, 2020, 08:28 PM
1
2--[[
3See BigWigs/Docs/BarStyles.txt for in-depth information on how to register new
4bar styles from 3rd party addons.
5]]
6
7--------------------------------------------------------------------------------
8-- Module Declaration
9--
10
11local plugin = BigWigs:NewPlugin("Bars")
12if not plugin then return end
13
14--------------------------------------------------------------------------------
15-- Locals
16--
17
18local colorize = nil
19do
20 local r, g, b
21 colorize = setmetatable({}, { __index =
22 function(self, key)
23 if not r then r, g, b = GameFontNormal:GetTextColor() end
24 self[key] = "|cff" .. ("%02x%02x%02x"):format(r * 255, g * 255, b * 255) .. key .. "|r"
25 return self[key]
26 end
27 })
28end
29
30local L = BigWigsAPI:GetLocale("BigWigs: Plugins")
31plugin.displayName = L.bars
32
33local startBreak -- Break timer function
34
35local colors = nil
36local candy = LibStub("LibCandyBar-3.0")
37local media = LibStub("LibSharedMedia-3.0")
38local FONT = media.MediaType and media.MediaType.FONT or "font"
39local STATUSBAR = media.MediaType and media.MediaType.STATUSBAR or "statusbar"
40local next = next
41local tremove = tremove
42local db = nil
43local normalAnchor, emphasizeAnchor = nil, nil
44local nameplateBars = {}
45local empUpdate = nil -- emphasize updater frame
46local nameplateEmpUpdate = nil
47local rearrangeBars
48local rearrangeNameplateBars
49local UnitGUID = UnitGUID
50local GetNamePlateForUnit = C_NamePlate.GetNamePlateForUnit
51
52local clickHandlers = {}
53
54local findUnitByGUID = nil
55do
56 local unitTable = {
57 "nameplate1", "nameplate2", "nameplate3", "nameplate4", "nameplate5", "nameplate6", "nameplate7", "nameplate8", "nameplate9", "nameplate10",
58 "nameplate11", "nameplate12", "nameplate13", "nameplate14", "nameplate15", "nameplate16", "nameplate17", "nameplate18", "nameplate19", "nameplate20",
59 "nameplate21", "nameplate22", "nameplate23", "nameplate24", "nameplate25", "nameplate26", "nameplate27", "nameplate28", "nameplate29", "nameplate30",
60 "nameplate31", "nameplate32", "nameplate33", "nameplate34", "nameplate35", "nameplate36", "nameplate37", "nameplate38", "nameplate39", "nameplate40",
61 }
62 local unitTableCount = #unitTable
63 findUnitByGUID = function(id)
64 for i = 1, unitTableCount do
65 local unit = unitTable[i]
66 local guid = UnitGUID(unit)
67 if guid == id then
68 return unit
69 end
70 end
71 end
72end
73
74--------------------------------------------------------------------------------
75-- Bar styles setup
76--
77
78local currentBarStyler = nil
79
80local barStyles = {
81 Default = {
82 apiVersion = 1,
83 version = 1,
84 --GetSpacing = function(bar) end,
85 --ApplyStyle = function(bar) end,
86 --BarStopped = function(bar) end,
87 GetStyleName = function()
88 return L.bigWigsBarStyleName_Default
89 end,
90 },
91}
92local barStyleRegister = {}
93
94do
95 -- !Beautycase styling, based on !Beatycase by Neal "Neave" @ WowI, texture made by Game92 "Aftermathh" @ WowI
96
97 local textureNormal = "Interface\\AddOns\\BigWigs\\Media\\Textures\\beautycase"
98
99 local backdropbc = {
100 bgFile = "Interface\\Buttons\\WHITE8x8",
101 insets = {top = 1, left = 1, bottom = 1, right = 1},
102 }
103
104 local function createBorder(self)
105 local border = UIParent:CreateTexture(nil, "OVERLAY")
106 border:SetParent(self)
107 border:SetTexture(textureNormal)
108 border:SetWidth(12)
109 border:SetHeight(12)
110 border:SetVertexColor(1, 1, 1)
111 return border
112 end
113
114 local freeBorderSets = {}
115
116 local function freeStyle(bar)
117 local borders = bar:Get("bigwigs:beautycase:borders")
118 if borders then
119 for i, border in next, borders do
120 border:SetParent(UIParent)
121 border:Hide()
122 end
123 freeBorderSets[#freeBorderSets + 1] = borders
124 end
125 end
126
127 local function styleBar(bar)
128 local bd = bar.candyBarBackdrop
129
130 bd:SetBackdrop(backdropbc)
131 bd:SetBackdropColor(.1, .1, .1, 1)
132
133 bd:ClearAllPoints()
134 bd:SetPoint("TOPLEFT", bar, "TOPLEFT", -1, 1)
135 bd:SetPoint("BOTTOMRIGHT", bar, "BOTTOMRIGHT", 1, -1)
136 bd:Show()
137
138 local borders = nil
139 if #freeBorderSets > 0 then
140 borders = tremove(freeBorderSets)
141 for i, border in next, borders do
142 border:SetParent(bar.candyBarBar)
143 border:ClearAllPoints()
144 border:Show()
145 end
146 else
147 borders = {}
148 for i = 1, 8 do
149 borders[i] = createBorder(bar.candyBarBar)
150 end
151 end
152 for i = 1, #borders do
153 local border = borders[i]
154 if i == 1 then
155 border:SetTexCoord(0, 1/3, 0, 1/3)
156 border:SetPoint("TOPLEFT", bar, "TOPLEFT", -4, 4)
157 elseif i == 2 then
158 border:SetTexCoord(2/3, 1, 0, 1/3)
159 border:SetPoint("TOPRIGHT", bar, "TOPRIGHT", 4, 4)
160 elseif i == 3 then
161 border:SetTexCoord(0, 1/3, 2/3, 1)
162 border:SetPoint("BOTTOMLEFT", bar, "BOTTOMLEFT", -4, -3)
163 elseif i == 4 then
164 border:SetTexCoord(2/3, 1, 2/3, 1)
165 border:SetPoint("BOTTOMRIGHT", bar, "BOTTOMRIGHT", 4, -3)
166 elseif i == 5 then
167 border:SetTexCoord(1/3, 2/3, 0, 1/3)
168 border:SetPoint("TOPLEFT", borders[1], "TOPRIGHT")
169 border:SetPoint("TOPRIGHT", borders[2], "TOPLEFT")
170 elseif i == 6 then
171 border:SetTexCoord(1/3, 2/3, 2/3, 1)
172 border:SetPoint("BOTTOMLEFT", borders[3], "BOTTOMRIGHT")
173 border:SetPoint("BOTTOMRIGHT", borders[4], "BOTTOMLEFT")
174 elseif i == 7 then
175 border:SetTexCoord(0, 1/3, 1/3, 2/3)
176 border:SetPoint("TOPLEFT", borders[1], "BOTTOMLEFT")
177 border:SetPoint("BOTTOMLEFT", borders[3], "TOPLEFT")
178 elseif i == 8 then
179 border:SetTexCoord(2/3, 1, 1/3, 2/3)
180 border:SetPoint("TOPRIGHT", borders[2], "BOTTOMRIGHT")
181 border:SetPoint("BOTTOMRIGHT", borders[4], "TOPRIGHT")
182 end
183 end
184
185 bar:Set("bigwigs:beautycase:borders", borders)
186 end
187
188 barStyles.BeautyCase = {
189 apiVersion = 1,
190 version = 10,
191 barSpacing = 8,
192 ApplyStyle = styleBar,
193 BarStopped = freeStyle,
194 GetStyleName = function() return "!Beautycase" end,
195 }
196end
197
198do
199 -- MonoUI
200 local backdropBorder = {
201 bgFile = "Interface\\ChatFrame\\ChatFrameBackground",
202 edgeFile = "Interface\\ChatFrame\\ChatFrameBackground",
203 tile = false, tileSize = 0, edgeSize = 1,
204 insets = {left = 0, right = 0, top = 0, bottom = 0}
205 }
206
207 local function removeStyle(bar)
208 bar.candyBarBackdrop:Hide()
209 local height = bar:Get("bigwigs:restoreheight")
210 if height then
211 bar:SetHeight(height)
212 end
213
214 local tex = bar:Get("bigwigs:restoreicon")
215 if tex then
216 bar:SetIcon(tex)
217 bar:Set("bigwigs:restoreicon", nil)
218
219 bar.candyBarIconFrameBackdrop:Hide()
220 end
221
222 bar.candyBarDuration:ClearAllPoints()
223 bar.candyBarDuration:SetPoint("TOPLEFT", bar.candyBarBar, "TOPLEFT", 2, 0)
224 bar.candyBarDuration:SetPoint("BOTTOMRIGHT", bar.candyBarBar, "BOTTOMRIGHT", -2, 0)
225
226 bar.candyBarLabel:ClearAllPoints()
227 bar.candyBarLabel:SetPoint("TOPLEFT", bar.candyBarBar, "TOPLEFT", 2, 0)
228 bar.candyBarLabel:SetPoint("BOTTOMRIGHT", bar.candyBarBar, "BOTTOMRIGHT", -2, 0)
229 end
230
231 local function styleBar(bar)
232 local height = bar:GetHeight()
233 bar:Set("bigwigs:restoreheight", height)
234 bar:SetHeight(height/2)
235
236 local bd = bar.candyBarBackdrop
237
238 bd:SetBackdrop(backdropBorder)
239 bd:SetBackdropColor(.1,.1,.1,1)
240 bd:SetBackdropBorderColor(0,0,0,1)
241
242 bd:ClearAllPoints()
243 bd:SetPoint("TOPLEFT", bar, "TOPLEFT", -2, 2)
244 bd:SetPoint("BOTTOMRIGHT", bar, "BOTTOMRIGHT", 2, -2)
245 bd:Show()
246
247 local tex = bar:GetIcon()
248 if tex then
249 local icon = bar.candyBarIconFrame
250 bar:SetIcon(nil)
251 icon:SetTexture(tex)
252 icon:Show()
253 if bar.iconPosition == "RIGHT" then
254 icon:SetPoint("BOTTOMLEFT", bar, "BOTTOMRIGHT", 5, 0)
255 else
256 icon:SetPoint("BOTTOMRIGHT", bar, "BOTTOMLEFT", -5, 0)
257 end
258 icon:SetSize(height, height)
259 bar:Set("bigwigs:restoreicon", tex)
260
261 local iconBd = bar.candyBarIconFrameBackdrop
262 iconBd:SetBackdrop(backdropBorder)
263 iconBd:SetBackdropColor(.1,.1,.1,1)
264 iconBd:SetBackdropBorderColor(0,0,0,1)
265
266 iconBd:ClearAllPoints()
267 iconBd:SetPoint("TOPLEFT", icon, "TOPLEFT", -2, 2)
268 iconBd:SetPoint("BOTTOMRIGHT", icon, "BOTTOMRIGHT", 2, -2)
269 iconBd:Show()
270 end
271
272 bar.candyBarLabel:ClearAllPoints()
273 bar.candyBarLabel:SetPoint("BOTTOMLEFT", bar.candyBarBar, "TOPLEFT", 2, 2)
274
275 bar.candyBarDuration:ClearAllPoints()
276 bar.candyBarDuration:SetPoint("BOTTOMRIGHT", bar.candyBarBar, "TOPRIGHT", -2, 2)
277 end
278
279 barStyles.MonoUI = {
280 apiVersion = 1,
281 version = 10,
282 barHeight = 20,
283 fontSizeNormal = 10,
284 fontSizeEmphasized = 11,
285 GetSpacing = function(bar) return bar:GetHeight()+6 end,
286 ApplyStyle = styleBar,
287 BarStopped = removeStyle,
288 GetStyleName = function() return "MonoUI" end,
289 }
290end
291
292do
293 -- Tukui
294 local C = Tukui and Tukui[2]
295 local backdrop = {
296 bgFile = "Interface\\Buttons\\WHITE8X8",
297 edgeFile = "Interface\\Buttons\\WHITE8X8",
298 tile = false, tileSize = 0, edgeSize = 1,
299 }
300 local borderBackdrop = {
301 edgeFile = "Interface\\Buttons\\WHITE8X8",
302 edgeSize = 1,
303 insets = { left = 1, right = 1, top = 1, bottom = 1 }
304 }
305
306 local function removeStyle(bar)
307 local bd = bar.candyBarBackdrop
308 bd:Hide()
309 if bd.tukiborder then
310 bd.tukiborder:Hide()
311 bd.tukoborder:Hide()
312 end
313 end
314
315 local function styleBar(bar)
316 local bd = bar.candyBarBackdrop
317 bd:SetBackdrop(backdrop)
318
319 if C then
320 bd:SetBackdropColor(unpack(C.Medias.BackdropColor))
321 bd:SetBackdropBorderColor(unpack(C.Medias.BorderColor))
322 bd:SetOutside(bar)
323 else
324 bd:SetBackdropColor(0.1,0.1,0.1)
325 bd:SetBackdropBorderColor(0.5,0.5,0.5)
326 bd:ClearAllPoints()
327 bd:SetPoint("TOPLEFT", bar, "TOPLEFT", -2, 2)
328 bd:SetPoint("BOTTOMRIGHT", bar, "BOTTOMRIGHT", 2, -2)
329 end
330
331 if not bd.tukiborder then
332 local border = CreateFrame("Frame", nil, bd)
333 if C then
334 border:SetInside(bd, 1, 1)
335 else
336 border:SetPoint("TOPLEFT", bd, "TOPLEFT", 1, -1)
337 border:SetPoint("BOTTOMRIGHT", bd, "BOTTOMRIGHT", -1, 1)
338 end
339 border:SetFrameLevel(3)
340 border:SetBackdrop(borderBackdrop)
341 border:SetBackdropBorderColor(0, 0, 0)
342 bd.tukiborder = border
343 else
344 bd.tukiborder:Show()
345 end
346
347 if not bd.tukoborder then
348 local border = CreateFrame("Frame", nil, bd)
349 if C then
350 border:SetOutside(bd, 1, 1)
351 else
352 border:SetPoint("TOPLEFT", bd, "TOPLEFT", -1, 1)
353 border:SetPoint("BOTTOMRIGHT", bd, "BOTTOMRIGHT", 1, -1)
354 end
355 border:SetFrameLevel(3)
356 border:SetBackdrop(borderBackdrop)
357 border:SetBackdropBorderColor(0, 0, 0)
358 bd.tukoborder = border
359 else
360 bd.tukoborder:Show()
361 end
362
363 bd:Show()
364 end
365
366 barStyles.TukUI = {
367 apiVersion = 1,
368 version = 10,
369 barSpacing = 7,
370 ApplyStyle = styleBar,
371 BarStopped = removeStyle,
372 GetStyleName = function() return "TukUI" end,
373 }
374end
375
376do
377 -- ElvUI
378 local E = ElvUI and ElvUI[1]
379 local backdropBorder = {
380 bgFile = "Interface\\Buttons\\WHITE8X8",
381 edgeFile = "Interface\\Buttons\\WHITE8X8",
382 tile = false, tileSize = 0, edgeSize = 1,
383 insets = {left = 0, right = 0, top = 0, bottom = 0}
384 }
385
386 local function removeStyle(bar)
387 local bd = bar.candyBarBackdrop
388 bd:Hide()
389 if bd.iborder then
390 bd.iborder:Hide()
391 bd.oborder:Hide()
392 end
393
394 local tex = bar:Get("bigwigs:restoreicon")
395 if tex then
396 bar:SetIcon(tex)
397 bar:Set("bigwigs:restoreicon", nil)
398
399 local iconBd = bar.candyBarIconFrameBackdrop
400 iconBd:Hide()
401 if iconBd.iborder then
402 iconBd.iborder:Hide()
403 iconBd.oborder:Hide()
404 end
405 end
406 end
407
408 local function styleBar(bar)
409 local bd = bar.candyBarBackdrop
410
411 if E then
412 bd:SetTemplate("Transparent")
413 bd:SetOutside(bar)
414 if not E.PixelMode and bd.iborder then
415 bd.iborder:Show()
416 bd.oborder:Show()
417 end
418 else
419 bd:SetBackdrop(backdropBorder)
420 bd:SetBackdropColor(0.06, 0.06, 0.06, 0.8)
421 bd:SetBackdropBorderColor(0, 0, 0)
422
423 bd:ClearAllPoints()
424 bd:SetPoint("TOPLEFT", bar, "TOPLEFT", -1, 1)
425 bd:SetPoint("BOTTOMRIGHT", bar, "BOTTOMRIGHT", 1, -1)
426 end
427
428 local tex = bar:GetIcon()
429 if tex then
430 local icon = bar.candyBarIconFrame
431 bar:SetIcon(nil)
432 icon:SetTexture(tex)
433 icon:Show()
434 if bar.iconPosition == "RIGHT" then
435 icon:SetPoint("BOTTOMLEFT", bar, "BOTTOMRIGHT", E and (E.PixelMode and 1 or 5) or 1, 0)
436 else
437 icon:SetPoint("BOTTOMRIGHT", bar, "BOTTOMLEFT", E and (E.PixelMode and -1 or -5) or -1, 0)
438 end
439 icon:SetSize(bar:GetHeight(), bar:GetHeight())
440 bar:Set("bigwigs:restoreicon", tex)
441
442 local iconBd = bar.candyBarIconFrameBackdrop
443
444 if E then
445 iconBd:SetTemplate("Transparent")
446 iconBd:SetOutside(bar.candyBarIconFrame)
447 if not E.PixelMode and iconBd.iborder then
448 iconBd.iborder:Show()
449 iconBd.oborder:Show()
450 end
451 else
452 iconBd:SetBackdrop(backdropBorder)
453 iconBd:SetBackdropColor(0.06, 0.06, 0.06, 0.8)
454 iconBd:SetBackdropBorderColor(0, 0, 0)
455
456 iconBd:ClearAllPoints()
457 iconBd:SetPoint("TOPLEFT", icon, "TOPLEFT", -1, 1)
458 iconBd:SetPoint("BOTTOMRIGHT", icon, "BOTTOMRIGHT", 1, -1)
459 end
460 iconBd:Show()
461 end
462
463 bd:Show()
464 end
465
466 barStyles.ElvUI = {
467 apiVersion = 1,
468 version = 10,
469 barSpacing = E and (E.PixelMode and 4 or 8) or 4,
470 barHeight = 20,
471 ApplyStyle = styleBar,
472 BarStopped = removeStyle,
473 GetStyleName = function() return "ElvUI" end,
474 }
475end
476
477--------------------------------------------------------------------------------
478-- Options
479--
480
481plugin.defaultDB = {
482 fontName = plugin:GetDefaultFont(),
483 fontSize = 10,
484 fontSizeEmph = 13,
485 texture = "BantoBar",
486 font = nil,
487 monochrome = nil,
488 outline = "NONE",
489 growup = true,
490 text = true,
491 time = true,
492 alignText = "LEFT",
493 alignTime = "RIGHT",
494 icon = true,
495 iconPosition = "LEFT",
496 fill = nil,
497 barStyle = "Default",
498 emphasize = true,
499 emphasizeMove = true,
500 emphasizeGrowup = nil,
501 emphasizeRestart = true,
502 emphasizeTime = 11,
503 emphasizeMultiplier = 1.1,
504 BigWigsAnchor_width = 220,
505 BigWigsAnchor_height = 16,
506 BigWigsEmphasizeAnchor_width = 320,
507 BigWigsEmphasizeAnchor_height = 22,
508 nameplateBars = true,
509 nameplateWidth = 150,
510 nameplateAutoWidth = true,
511 nameplateHeight = 16,
512 nameplateOffsetY = 30,
513 nameplateGrowUp = true,
514 spacing = 1,
515 visibleBarLimit = 100,
516 visibleBarLimitEmph = 100,
517 interceptMouse = nil,
518 onlyInterceptOnKeypress = nil,
519 interceptKey = "CTRL",
520 LeftButton = {
521 report = true,
522 },
523 MiddleButton = {
524 remove = true,
525 },
526 RightButton = {
527 emphasize = true,
528 },
529}
530
531do
532 local clickOptions = {
533 emphasize = {
534 type = "toggle",
535 name = colorize[L.superEmphasize],
536 desc = L.tempEmphasize,
537 descStyle = "inline",
538 order = 1,
539 },
540 report = {
541 type = "toggle",
542 name = colorize[L.report],
543 desc = L.reportDesc,
544 descStyle = "inline",
545 order = 2,
546 },
547 remove = {
548 type = "toggle",
549 name = colorize[L.remove],
550 desc = L.removeDesc,
551 descStyle = "inline",
552 order = 3,
553 },
554 removeOther = {
555 type = "toggle",
556 name = colorize[L.removeOther],
557 desc = L.removeOtherDesc,
558 descStyle = "inline",
559 order = 4,
560 },
561 disable = {
562 type = "toggle",
563 name = colorize[L.disable],
564 desc = L.disableDesc,
565 descStyle = "inline",
566 order = 5,
567 },
568 }
569
570 local function updateFont(info, value)
571 if info then
572 local key = info[#info]
573 if key == "fontName" then
574 local list = media:List(FONT)
575 db[key] = list[value]
576 else
577 db[key] = value
578 end
579 end
580
581 local flags = nil
582 if db.monochrome and db.outline ~= "NONE" then
583 flags = "MONOCHROME," .. db.outline
584 elseif db.monochrome then
585 flags = "MONOCHROME"
586 elseif db.outline ~= "NONE" then
587 flags = db.outline
588 end
589 local f = media:Fetch(FONT, db.fontName)
590 for bar in next, normalAnchor.bars do
591 bar.candyBarLabel:SetFont(f, db.fontSize, flags)
592 bar.candyBarDuration:SetFont(f, db.fontSize, flags)
593 end
594 for bar in next, emphasizeAnchor.bars do
595 bar.candyBarLabel:SetFont(f, db.fontSizeEmph, flags)
596 bar.candyBarDuration:SetFont(f, db.fontSizeEmph, flags)
597 end
598 end
599
600 local function sortBars(info, value)
601 db[info[#info]] = value
602 rearrangeBars(normalAnchor)
603 rearrangeBars(emphasizeAnchor)
604 end
605
606 local function shouldDisable() return not plugin.db.profile.interceptMouse end
607 plugin.pluginOptions = {
608 type = "group",
609 name = L.bars,
610 childGroups = "tab",
611 get = function(info)
612 return db[info[#info]]
613 end,
614 set = function(info, value)
615 db[info[#info]] = value
616 if BigWigsAnchor then
617 BigWigsAnchor:RefixPosition()
618 BigWigsEmphasizeAnchor:RefixPosition()
619 end
620 end,
621 args = {
622 custom = {
623 type = "group",
624 name = L.general,
625 order = 1,
626 args = {
627 fontName = {
628 type = "select",
629 name = L.font,
630 order = 1,
631 values = media:List(FONT),
632 itemControl = "DDI-Font",
633 get = function(info)
634 for i, v in next, media:List(FONT) do
635 if v == db.fontName then return i end
636 end
637 end,
638 set = updateFont,
639 },
640 outline = {
641 type = "select",
642 name = L.outline,
643 order = 2,
644 values = {
645 NONE = L.none,
646 OUTLINE = L.thin,
647 THICKOUTLINE = L.thick,
648 },
649 set = updateFont,
650 },
651 monochrome = {
652 type = "toggle",
653 name = L.monochrome,
654 desc = L.monochromeDesc,
655 order = 3,
656 set = updateFont,
657 },
658 header1 = {
659 type = "header",
660 name = "",
661 order = 4,
662 },
663 barStyle = {
664 type = "select",
665 name = L.style,
666 order = 5,
667 values = barStyleRegister,
668 set = function(info, value)
669 db[info[#info]] = value
670 plugin:SetBarStyle(value)
671 local style = barStyles[value]
672 if style then
673 if style.barSpacing then
674 db.spacing = style.barSpacing
675 else
676 db.spacing = 1
677 end
678 rearrangeBars(normalAnchor)
679 rearrangeBars(emphasizeAnchor)
680
681 if style.barHeight then
682 db.BigWigsAnchor_height = style.barHeight
683 db.BigWigsEmphasizeAnchor_height = style.barHeight * 1.1
684 else
685 db.BigWigsAnchor_height = 16
686 db.BigWigsEmphasizeAnchor_height = 22
687 end
688 if style.fontSizeNormal then
689 db.fontSize = style.fontSizeNormal
690 updateFont()
691 end
692 if style.fontSizeEmphasized then
693 db.fontSizeEmph = style.fontSizeEmphasized
694 updateFont()
695 end
696
697 for bar in next, normalAnchor.bars do
698 currentBarStyler.BarStopped(bar)
699 bar:SetHeight(db.BigWigsAnchor_height)
700 currentBarStyler.ApplyStyle(bar)
701 end
702 for bar in next, emphasizeAnchor.bars do
703 currentBarStyler.BarStopped(bar)
704 bar:SetHeight(db.BigWigsEmphasizeAnchor_height)
705 currentBarStyler.ApplyStyle(bar)
706 end
707
708 BigWigsAnchor:RefixPosition()
709 BigWigsEmphasizeAnchor:RefixPosition()
710 plugin:UpdateGUI()
711 end
712 end,
713 },
714 spacing = {
715 type = "range",
716 name = L.spacing,
717 desc = L.spacingDesc,
718 order = 6,
719 softMax = 30,
720 min = 0,
721 step = 1,
722 width = 2,
723 set = sortBars,
724 disabled = function()
725 -- Just throw in a random frame (normalAnchor) instead of a bar to see if it returns a value since we noop() styles that don't have a .GetSpacing entry
726 return currentBarStyler.GetSpacing(normalAnchor)
727 end,
728 },
729 fill = {
730 type = "toggle",
731 name = L.fill,
732 desc = L.fillDesc,
733 order = 7,
734 set = function(info, value)
735 db[info[#info]] = value
736 for bar in next, normalAnchor.bars do
737 bar:SetFill(value)
738 end
739 for bar in next, emphasizeAnchor.bars do
740 bar:SetFill(value)
741 end
742 end,
743 },
744 texture = {
745 type = "select",
746 name = L.texture,
747 order = 8,
748 width = 2,
749 values = media:List(STATUSBAR),
750 itemControl = "DDI-Statusbar",
751 get = function(info)
752 for i, v in next, media:List(STATUSBAR) do
753 if v == db[info[#info]] then return i end
754 end
755 end,
756 set = function(info, value)
757 local list = media:List(STATUSBAR)
758 local tex = list[value]
759 db[info[#info]] = tex
760 for bar in next, normalAnchor.bars do
761 currentBarStyler.BarStopped(bar)
762 bar:SetTexture(media:Fetch(STATUSBAR, tex))
763 currentBarStyler.ApplyStyle(bar)
764 end
765 for bar in next, emphasizeAnchor.bars do
766 currentBarStyler.BarStopped(bar)
767 bar:SetTexture(media:Fetch(STATUSBAR, tex))
768 currentBarStyler.ApplyStyle(bar)
769 end
770 end,
771 },
772 header2 = {
773 type = "header",
774 name = "",
775 order = 9,
776 },
777 text = {
778 type = "toggle",
779 name = L.text,
780 desc = L.textDesc,
781 order = 10,
782 set = function(info, value)
783 db[info[#info]] = value
784 for bar in next, normalAnchor.bars do
785 currentBarStyler.BarStopped(bar)
786 bar:SetLabelVisibility(value)
787 currentBarStyler.ApplyStyle(bar)
788 end
789 for bar in next, emphasizeAnchor.bars do
790 currentBarStyler.BarStopped(bar)
791 bar:SetLabelVisibility(value)
792 currentBarStyler.ApplyStyle(bar)
793 end
794 end,
795 },
796 alignText = {
797 type = "select",
798 name = L.alignText,
799 order = 11,
800 values = {
801 LEFT = L.left,
802 CENTER = L.center,
803 RIGHT = L.right,
804 },
805 set = function(info, value)
806 db[info[#info]] = value
807 for bar in next, normalAnchor.bars do
808 currentBarStyler.BarStopped(bar)
809 bar.candyBarLabel:SetJustifyH(value)
810 currentBarStyler.ApplyStyle(bar)
811 end
812 for bar in next, emphasizeAnchor.bars do
813 currentBarStyler.BarStopped(bar)
814 bar.candyBarLabel:SetJustifyH(value)
815 currentBarStyler.ApplyStyle(bar)
816 end
817 end,
818 },
819 textSpacer = {
820 type = "description",
821 name = " ",
822 order = 12,
823 },
824 time = {
825 type = "toggle",
826 name = L.time,
827 desc = L.timeDesc,
828 order = 13,
829 set = function(info, value)
830 db[info[#info]] = value
831 for bar in next, normalAnchor.bars do
832 currentBarStyler.BarStopped(bar)
833 bar:SetTimeVisibility(value)
834 currentBarStyler.ApplyStyle(bar)
835 end
836 for bar in next, emphasizeAnchor.bars do
837 currentBarStyler.BarStopped(bar)
838 bar:SetTimeVisibility(value)
839 currentBarStyler.ApplyStyle(bar)
840 end
841 end,
842 },
843 alignTime = {
844 type = "select",
845 name = L.alignTime,
846 order = 14,
847 values = {
848 LEFT = L.left,
849 CENTER = L.center,
850 RIGHT = L.right,
851 },
852 set = function(info, value)
853 db[info[#info]] = value
854 for bar in next, normalAnchor.bars do
855 currentBarStyler.BarStopped(bar)
856 bar.candyBarDuration:SetJustifyH(value)
857 currentBarStyler.ApplyStyle(bar)
858 end
859 for bar in next, emphasizeAnchor.bars do
860 currentBarStyler.BarStopped(bar)
861 bar.candyBarDuration:SetJustifyH(value)
862 currentBarStyler.ApplyStyle(bar)
863 end
864 end,
865 },
866 timeSpacer = {
867 type = "description",
868 name = " ",
869 order = 15,
870 },
871 icon = {
872 type = "toggle",
873 name = L.icon,
874 desc = L.iconDesc,
875 order = 16,
876 set = function(info, value)
877 db[info[#info]] = value
878 for bar in next, normalAnchor.bars do
879 currentBarStyler.BarStopped(bar)
880 if value then
881 bar:SetIcon(bar:Get("bigwigs:iconoptionrestore") or 134337) -- Interface/Icons/INV_Misc_Orb_05
882 else
883 bar:Set("bigwigs:iconoptionrestore", bar:GetIcon())
884 bar:SetIcon(nil)
885 end
886 currentBarStyler.ApplyStyle(bar)
887 end
888 for bar in next, emphasizeAnchor.bars do
889 currentBarStyler.BarStopped(bar)
890 if value then
891 bar:SetIcon(bar:Get("bigwigs:iconoptionrestore") or 134337) -- Interface/Icons/INV_Misc_Orb_05
892 else
893 bar:Set("bigwigs:iconoptionrestore", bar:GetIcon())
894 bar:SetIcon(nil)
895 end
896 currentBarStyler.ApplyStyle(bar)
897 end
898 end,
899 },
900 iconPosition = {
901 type = "select",
902 name = L.iconPosition,
903 desc = L.iconPositionDesc,
904 order = 17,
905 values = {
906 LEFT = L.left,
907 RIGHT = L.right,
908 },
909 set = function(info, value)
910 db[info[#info]] = value
911 for bar in next, normalAnchor.bars do
912 currentBarStyler.BarStopped(bar)
913 bar:SetIconPosition(value)
914 currentBarStyler.ApplyStyle(bar)
915 end
916 for bar in next, emphasizeAnchor.bars do
917 currentBarStyler.BarStopped(bar)
918 bar:SetIconPosition(value)
919 currentBarStyler.ApplyStyle(bar)
920 end
921 end,
922 disabled = function() return not db.icon end,
923 },
924 },
925 },
926 normal = {
927 type = "group",
928 name = L.regularBars,
929 order = 2,
930 args = {
931 growup = {
932 type = "toggle",
933 name = L.growingUpwards,
934 desc = L.growingUpwardsDesc,
935 order = 1,
936 set = sortBars,
937 },
938 visibleBarLimit = {
939 type = "range",
940 name = L.visibleBarLimit,
941 desc = L.visibleBarLimitDesc,
942 order = 2,
943 max = 100,
944 min = 1,
945 step = 1,
946 set = sortBars,
947 },
948 fontSize = {
949 type = "range",
950 name = L.fontSize,
951 width = 2,
952 order = 3,
953 max = 200, softMax = 72,
954 min = 1,
955 step = 1,
956 set = updateFont,
957 },
958 exactPositioning = {
959 type = "group",
960 name = L.positionExact,
961 order = 4,
962 inline = true,
963 args = {
964 BigWigsAnchor_x = {
965 type = "range",
966 name = L.positionX,
967 desc = L.positionDesc,
968 min = 0,
969 softMax = 2048,
970 step = 1,
971 order = 1,
972 width = 3.2,
973 },
974 BigWigsAnchor_y = {
975 type = "range",
976 name = L.positionY,
977 desc = L.positionDesc,
978 min = 0,
979 softMax = 2048,
980 step = 1,
981 order = 2,
982 width = 3.2,
983 },
984 BigWigsAnchor_width = {
985 type = "range",
986 name = L.width,
987 desc = L.sizeDesc,
988 min = 80,
989 softMax = 2000,
990 step = 1,
991 order = 3,
992 width = 1.6,
993 },
994 BigWigsAnchor_height = {
995 type = "range",
996 name = L.height,
997 desc = L.sizeDesc,
998 min = 8,
999 softMax = 150,
1000 step = 1,
1001 order = 4,
1002 width = 1.6,
1003 },
1004 },
1005 },
1006 },
1007 },
1008 emphasize = {
1009 type = "group",
1010 name = L.emphasizedBars,
1011 order = 3,
1012 args = {
1013 emphasize = {
1014 type = "toggle",
1015 name = L.enable,
1016 order = 1,
1017 },
1018 emphasizeRestart = {
1019 type = "toggle",
1020 name = L.restart,
1021 desc = L.restartDesc,
1022 order = 2,
1023 },
1024 emphasizeGrowup = {
1025 type = "toggle",
1026 name = L.growingUpwards,
1027 desc = L.growingUpwardsDesc,
1028 order = 3,
1029 set = sortBars,
1030 },
1031 emphasizeMove = {
1032 type = "toggle",
1033 name = L.move,
1034 desc = L.moveDesc,
1035 order = 4,
1036 set = function(_, value)
1037 db.emphasizeMove = value
1038 if not value then
1039 db.BigWigsEmphasizeAnchor_width = db.BigWigsAnchor_width*db.emphasizeMultiplier
1040 db.BigWigsEmphasizeAnchor_height = db.BigWigsAnchor_height*db.emphasizeMultiplier
1041 else
1042 db.BigWigsEmphasizeAnchor_width = BigWigsEmphasizeAnchor:GetWidth()
1043 db.BigWigsEmphasizeAnchor_height = BigWigsEmphasizeAnchor:GetHeight()
1044 end
1045 end,
1046 },
1047 emphasizeMultiplier = {
1048 type = "range",
1049 name = L.emphasizeMultiplier,
1050 desc = L.emphasizeMultiplierDesc,
1051 width = 2,
1052 order = 5,
1053 max = 3,
1054 min = 1,
1055 step = 0.01,
1056 set = function(_, value)
1057 db.emphasizeMultiplier = value
1058 db.BigWigsEmphasizeAnchor_width = db.BigWigsAnchor_width*value
1059 db.BigWigsEmphasizeAnchor_height = db.BigWigsAnchor_height*value
1060 end,
1061 disabled = function() return db.emphasizeMove end,
1062 },
1063 emphasizeTime = {
1064 type = "range",
1065 name = L.emphasizeAt,
1066 order = 6,
1067 min = 6,
1068 max = 20,
1069 step = 1,
1070 },
1071 fontSizeEmph = {
1072 type = "range",
1073 name = L.fontSize,
1074 order = 7,
1075 max = 200, softMax = 72,
1076 min = 1,
1077 step = 1,
1078 set = updateFont,
1079 },
1080 visibleBarLimitEmph = {
1081 type = "range",
1082 name = L.visibleBarLimit,
1083 desc = L.visibleBarLimitDesc,
1084 order = 8,
1085 max = 100,
1086 min = 1,
1087 step = 1,
1088 set = sortBars,
1089 },
1090 exactPositioning = {
1091 type = "group",
1092 name = L.positionExact,
1093 order = 9,
1094 inline = true,
1095 args = {
1096 BigWigsEmphasizeAnchor_x = {
1097 type = "range",
1098 name = L.positionX,
1099 desc = L.positionDesc,
1100 min = 0,
1101 softMax = 2048,
1102 step = 1,
1103 order = 1,
1104 width = 3.2,
1105 },
1106 BigWigsEmphasizeAnchor_y = {
1107 type = "range",
1108 name = L.positionY,
1109 desc = L.positionDesc,
1110 min = 0,
1111 softMax = 2048,
1112 step = 1,
1113 order = 2,
1114 width = 3.2,
1115 },
1116 BigWigsEmphasizeAnchor_width = {
1117 type = "range",
1118 name = L.width,
1119 desc = L.sizeDesc,
1120 min = 80,
1121 softMax = 2000,
1122 step = 1,
1123 order = 3,
1124 width = 1.6,
1125 },
1126 BigWigsEmphasizeAnchor_height = {
1127 type = "range",
1128 name = L.height,
1129 desc = L.sizeDesc,
1130 min = 8,
1131 softMax = 150,
1132 step = 1,
1133 order = 4,
1134 width = 1.6,
1135 },
1136 },
1137 },
1138 },
1139 },
1140 nameplateBars = {
1141 name = L.nameplateBars,
1142 type = "group",
1143 order = 4,
1144 args = {
1145 nameplateBars = {
1146 type = "toggle",
1147 name = L.enable,
1148 order = 1,
1149 },
1150 nameplateWidth = {
1151 type = "range",
1152 name = L.width,
1153 order = 2,
1154 min = 100,
1155 softMax = 500,
1156 step = 1,
1157 width = 1.6,
1158 disabled = function() return db.nameplateAutoWidth end,
1159 },
1160 nameplateHeight = {
1161 type = "range",
1162 name = L.height,
1163 order = 3,
1164 min = 8,
1165 softMax = 50,
1166 step = 1,
1167 width = 1.6,
1168 },
1169 nameplateAutoWidth = {
1170 type = "toggle",
1171 name = L.nameplateAutoWidth,
1172 desc = L.nameplateAutoWidthDesc,
1173 order = 4,
1174 width = 1.6,
1175 },
1176 nameplateOffsetY = {
1177 type = "range",
1178 name = L.nameplateOffsetY,
1179 desc = L.nameplateOffsetYDesc,
1180 order = 5,
1181 min = 0,
1182 max = 400,
1183 width = 1.6,
1184 },
1185 nameplateGrowUp = {
1186 type = "toggle",
1187 name = L.growingUpwards,
1188 desc = L.growingUpwardsDesc,
1189 order = 6,
1190 width = 1.6,
1191 },
1192 },
1193 },
1194 clicking = {
1195 name = L.clickableBars,
1196 type = "group",
1197 order = 5,
1198 childGroups = "tab",
1199 get = function(i) return plugin.db.profile[i[#i]] end,
1200 set = function(i, value)
1201 local key = i[#i]
1202 plugin.db.profile[key] = value
1203 if key == "interceptMouse" then
1204 plugin:RefixClickIntercepts()
1205 end
1206 end,
1207 args = {
1208 heading = {
1209 type = "description",
1210 name = L.clickableBarsDesc,
1211 order = 1,
1212 width = "full",
1213 fontSize = "medium",
1214 },
1215 interceptMouse = {
1216 type = "toggle",
1217 name = L.enable,
1218 desc = L.interceptMouseDesc,
1219 order = 2,
1220 width = "full",
1221 },
1222 onlyInterceptOnKeypress = {
1223 type = "toggle",
1224 name = L.modifierKey,
1225 desc = L.modifierKeyDesc,
1226 order = 3,
1227 disabled = shouldDisable,
1228 },
1229 interceptKey = {
1230 type = "select",
1231 name = L.modifier,
1232 desc = L.modifierDesc,
1233 values = {
1234 CTRL = _G.CTRL_KEY,
1235 ALT = _G.ALT_KEY,
1236 SHIFT = _G.SHIFT_KEY,
1237 },
1238 order = 4,
1239 disabled = function()
1240 return not plugin.db.profile.interceptMouse or not plugin.db.profile.onlyInterceptOnKeypress
1241 end,
1242 },
1243 left = {
1244 type = "group",
1245 name = KEY_BUTTON1 or "Left",
1246 order = 10,
1247 args = clickOptions,
1248 disabled = shouldDisable,
1249 get = function(info) return plugin.db.profile.LeftButton[info[#info]] end,
1250 set = function(info, value) plugin.db.profile.LeftButton[info[#info]] = value end,
1251 },
1252 middle = {
1253 type = "group",
1254 name = KEY_BUTTON3 or "Middle",
1255 order = 11,
1256 args = clickOptions,
1257 disabled = shouldDisable,
1258 get = function(info) return plugin.db.profile.MiddleButton[info[#info]] end,
1259 set = function(info, value) plugin.db.profile.MiddleButton[info[#info]] = value end,
1260 },
1261 right = {
1262 type = "group",
1263 name = KEY_BUTTON2 or "Right",
1264 order = 12,
1265 args = clickOptions,
1266 disabled = shouldDisable,
1267 get = function(info) return plugin.db.profile.RightButton[info[#info]] end,
1268 set = function(info, value) plugin.db.profile.RightButton[info[#info]] = value end,
1269 },
1270 },
1271 },
1272 },
1273 }
1274end
1275
1276--------------------------------------------------------------------------------
1277-- Bar arrangement
1278--
1279
1280do
1281 local function barSorter(a, b)
1282 return a.remaining < b.remaining and true or false
1283 end
1284 local tmp = {}
1285 rearrangeBars = function(anchor)
1286 if not anchor then return end
1287 if anchor == normalAnchor then -- only show the empupdater when there are bars on the normal anchor running
1288 if next(anchor.bars) and db.emphasize then
1289 empUpdate:Play()
1290 else
1291 empUpdate:Stop()
1292 end
1293 end
1294 if not next(anchor.bars) then return end
1295
1296 wipe(tmp)
1297 for bar in next, anchor.bars do
1298 tmp[#tmp + 1] = bar
1299 end
1300 table.sort(tmp, barSorter)
1301 local lastBar = nil
1302 local up, barLimit
1303 if anchor == normalAnchor then
1304 up = db.growup
1305 barLimit = db.visibleBarLimit
1306 else
1307 up = db.emphasizeGrowup
1308 barLimit = db.visibleBarLimitEmph
1309 end
1310 for i = 1, #tmp do
1311 local bar = tmp[i]
1312 if i > barLimit then
1313 bar:SetAlpha(0)
1314 bar:EnableMouse(false)
1315 elseif barLimit ~= 100 then
1316 bar:SetAlpha(1)
1317 if db.interceptMouse and not db.onlyInterceptOnKeypress then
1318 bar:EnableMouse(true)
1319 end
1320 end
1321 local spacing = currentBarStyler.GetSpacing(bar) or db.spacing
1322 bar:ClearAllPoints()
1323 if up or (db.emphasizeGrowup and bar:Get("bigwigs:emphasized")) then
1324 if lastBar then -- Growing from a bar
1325 bar:SetPoint("BOTTOMLEFT", lastBar, "TOPLEFT", 0, spacing)
1326 else -- Growing from the anchor
1327 bar:SetPoint("BOTTOMLEFT", anchor, "BOTTOMLEFT")
1328 end
1329 lastBar = bar
1330 else
1331 if lastBar then -- Growing from a bar
1332 bar:SetPoint("TOPLEFT", lastBar, "BOTTOMLEFT", 0, -spacing)
1333 else -- Growing from the anchor
1334 bar:SetPoint("BOTTOMLEFT", anchor, "BOTTOMLEFT")
1335 end
1336 lastBar = bar
1337 end
1338 end
1339 end
1340end
1341
1342do
1343 -- returns table of bar texts ordered by time remaining
1344 local function getOrder(bars)
1345 local barTexts = {}
1346 for text, _ in pairs(bars) do
1347 barTexts[#barTexts+1] = text
1348 end
1349 table.sort(barTexts, function(a, b)
1350 return bars[a].bar.remaining < bars[b].bar.remaining
1351 end)
1352 return barTexts
1353 end
1354
1355 rearrangeNameplateBars = function(guid)
1356 local unit = findUnitByGUID(guid)
1357 if not unit then return end
1358 local nameplate = GetNamePlateForUnit(unit)
1359 local unitBars = nameplateBars[guid]
1360 if unitBars then
1361 local sorted = getOrder(nameplateBars[guid])
1362 local offset = db.nameplateOffsetY
1363 local barPoint = db.nameplateGrowUp and "BOTTOM" or "TOP"
1364 local nameplatePoint = db.nameplateGrowUp and "TOP" or "BOTTOM"
1365 for i, text in ipairs(sorted) do
1366 local bar = unitBars[text].bar
1367 bar:ClearAllPoints()
1368 bar:SetParent(nameplate)
1369 bar:SetPoint(barPoint, nameplate, nameplatePoint, 0, db.nameplateGrowUp and offset or -offset)
1370 offset = offset + db.spacing + bar:GetHeight() end
1371 end
1372 end
1373end
1374
1375local function nameplateCascadeDelete(guid, text)
1376 nameplateBars[guid][text] = nil
1377 if not next(nameplateBars[guid]) then
1378 nameplateBars[guid] = nil
1379 if not next(nameplateBars) then
1380 nameplateEmpUpdate:Stop()
1381 end
1382 end
1383end
1384
1385local function createDeletionTimer(barInfo)
1386 return C_Timer.NewTimer(barInfo.exp - GetTime(), function()
1387 nameplateCascadeDelete(barInfo.unitGUID, barInfo.text)
1388 end)
1389end
1390
1391local function barStopped(event, bar)
1392 local a = bar:Get("bigwigs:anchor")
1393 local unitGUID = bar:Get("bigwigs:unitGUID")
1394 if a and a.bars and a.bars[bar] then
1395 currentBarStyler.BarStopped(bar)
1396 a.bars[bar] = nil
1397 rearrangeBars(a)
1398 elseif unitGUID then
1399 currentBarStyler.BarStopped(bar)
1400 local text = bar:GetLabel()
1401 nameplateBars[unitGUID][text].bar = nil
1402 if not bar:Get("bigwigs:offscreen") then
1403 nameplateCascadeDelete(unitGUID, text)
1404 rearrangeNameplateBars(unitGUID)
1405 end
1406 end
1407end
1408
1409--------------------------------------------------------------------------------
1410-- Anchors
1411--
1412
1413local defaultPositions = {
1414 BigWigsAnchor = {"CENTER", "UIParent", "CENTER", 0, -120},
1415 BigWigsEmphasizeAnchor = {"TOP", RaidWarningFrame, "BOTTOM", 0, -35}, --Below the Blizzard "Raid Warning" frame
1416}
1417
1418local function onDragHandleMouseDown(self) self:GetParent():StartSizing("BOTTOMRIGHT") end
1419local function onDragHandleMouseUp(self) self:GetParent():StopMovingOrSizing() end
1420local function onResize(self, width, height)
1421 db[self.w] = width
1422 db[self.h] = height
1423 if self == normalAnchor and not db.emphasizeMove then
1424 -- Move is disabled and we are configuring the normal anchor. Make sure to update the emphasized bars also.
1425 db[emphasizeAnchor.w] = width * db.emphasizeMultiplier
1426 db[emphasizeAnchor.h] = height * db.emphasizeMultiplier
1427 end
1428 for k in next, self.bars do
1429 currentBarStyler.BarStopped(k)
1430 if db.emphasizeMove then
1431 k:SetSize(width, height) -- Move enabled, set the size no matter which anchor we are configuring
1432 elseif self == normalAnchor then
1433 -- Move is disabled and we are configuring the normal anchor. Don't apply normal bar sizes to emphasized bars
1434 if k:Get("bigwigs:emphasized") then
1435 k:SetSize(db[emphasizeAnchor.w], db[emphasizeAnchor.h])
1436 else
1437 k:SetSize(width, height)
1438 end
1439 end
1440 currentBarStyler.ApplyStyle(k)
1441 rearrangeBars(self)
1442 end
1443 plugin:UpdateGUI() -- Update width/height if GUI is open
1444end
1445local function onDragStart(self) self:StartMoving() end
1446local function onDragStop(self)
1447 self:StopMovingOrSizing()
1448 local s = self:GetEffectiveScale()
1449 db[self.x] = self:GetLeft() * s
1450 db[self.y] = self:GetTop() * s
1451 plugin:UpdateGUI() -- Update X/Y if GUI is open
1452end
1453
1454do
1455 local function createAnchor(frameName, title)
1456 local display = CreateFrame("Frame", frameName, UIParent)
1457 display.w, display.h, display.x, display.y = frameName .. "_width", frameName .. "_height", frameName .. "_x", frameName .. "_y"
1458 display:EnableMouse(true)
1459 display:SetClampedToScreen(true)
1460 display:SetMovable(true)
1461 display:SetResizable(true)
1462 display:RegisterForDrag("LeftButton")
1463 display:SetMinResize(80, 8)
1464 display:SetFrameLevel(20)
1465 local bg = display:CreateTexture(nil, "BACKGROUND")
1466 bg:SetAllPoints(display)
1467 bg:SetColorTexture(0, 0, 0, 0.3)
1468 display.background = bg
1469 local header = display:CreateFontString(nil, "ARTWORK")
1470 header:SetFont(plugin:GetDefaultFont(12))
1471 header:SetShadowOffset(1, -1)
1472 header:SetTextColor(1,0.82,0,1)
1473 header:SetText(title)
1474 header:SetAllPoints(display)
1475 header:SetJustifyH("CENTER")
1476 header:SetJustifyV("MIDDLE")
1477 local drag = CreateFrame("Frame", nil, display)
1478 drag:SetFrameLevel(display:GetFrameLevel() + 10)
1479 drag:SetWidth(16)
1480 drag:SetHeight(16)
1481 drag:SetPoint("BOTTOMRIGHT", display, -1, 1)
1482 drag:EnableMouse(true)
1483 drag:SetScript("OnMouseDown", onDragHandleMouseDown)
1484 drag:SetScript("OnMouseUp", onDragHandleMouseUp)
1485 drag:SetAlpha(0.5)
1486 local tex = drag:CreateTexture(nil, "OVERLAY")
1487 tex:SetTexture("Interface\\AddOns\\BigWigs\\Media\\Textures\\draghandle")
1488 tex:SetWidth(16)
1489 tex:SetHeight(16)
1490 tex:SetBlendMode("ADD")
1491 tex:SetPoint("CENTER", drag)
1492 display:SetScript("OnSizeChanged", onResize)
1493 display:SetScript("OnDragStart", onDragStart)
1494 display:SetScript("OnDragStop", onDragStop)
1495 display.bars = {}
1496 display.Reset = function(self)
1497 db[self.x] = nil
1498 db[self.y] = nil
1499 db[self.w] = nil
1500 db[self.h] = nil
1501 self:RefixPosition()
1502 end
1503 display.RefixPosition = function(self)
1504 self:ClearAllPoints()
1505 if db[self.x] and db[self.y] then
1506 local s = self:GetEffectiveScale()
1507 self:SetPoint("TOPLEFT", UIParent, "BOTTOMLEFT", db[self.x] / s, db[self.y] / s)
1508 else
1509 self:SetPoint(unpack(defaultPositions[self:GetName()]))
1510 end
1511 self:SetWidth(db[self.w] or plugin.defaultDB[self.w])
1512 self:SetHeight(db[self.h] or plugin.defaultDB[self.h])
1513 end
1514 display:Hide()
1515 return display
1516 end
1517
1518 normalAnchor = createAnchor("BigWigsAnchor", L.bars)
1519 emphasizeAnchor = createAnchor("BigWigsEmphasizeAnchor", L.emphasizedBars)
1520end
1521
1522local function showAnchors()
1523 normalAnchor:Show()
1524 emphasizeAnchor:Show()
1525end
1526
1527local function hideAnchors()
1528 normalAnchor:Hide()
1529 emphasizeAnchor:Hide()
1530end
1531
1532local function resetAnchors()
1533 normalAnchor:Reset()
1534 emphasizeAnchor:Reset()
1535end
1536
1537local function updateProfile()
1538 db = plugin.db.profile
1539 normalAnchor:RefixPosition()
1540 emphasizeAnchor:RefixPosition()
1541 if plugin:IsEnabled() then
1542 if not media:Fetch(STATUSBAR, db.texture, true) then db.texture = "BantoBar" end
1543 plugin:SetBarStyle(db.barStyle)
1544 plugin:RegisterMessage("DBM_AddonMessage")
1545 end
1546 -- XXX temp cleanup [8.0.1]
1547 db.scale = nil
1548 db.emphasizeScale = nil
1549 if not db.emphasizeMove then
1550 db.BigWigsEmphasizeAnchor_width = db.BigWigsAnchor_width*db.emphasizeMultiplier
1551 db.BigWigsEmphasizeAnchor_height = db.BigWigsAnchor_height*db.emphasizeMultiplier
1552 end
1553 db.tempMonoUIReset = nil
1554 db.tempSpacingReset = nil
1555 db.font = nil
1556end
1557
1558--------------------------------------------------------------------------------
1559-- Initialization
1560--
1561
1562function plugin:OnRegister()
1563 candy.RegisterCallback(self, "LibCandyBar_Stop", barStopped)
1564
1565 self:RegisterMessage("BigWigs_ProfileUpdate", updateProfile)
1566 updateProfile()
1567
1568 for k, v in next, barStyles do
1569 barStyleRegister[k] = v:GetStyleName()
1570 end
1571end
1572
1573function plugin:OnPluginEnable()
1574 colors = BigWigs:GetPlugin("Colors")
1575 updateProfile()
1576
1577 self:RegisterMessage("BigWigs_StartBar")
1578 self:RegisterMessage("BigWigs_StartNameplateBar")
1579 self:RegisterMessage("BigWigs_PauseBar", "PauseBar")
1580 self:RegisterMessage("BigWigs_PauseNameplateBar", "PauseNameplateBar")
1581 self:RegisterMessage("BigWigs_ResumeBar", "ResumeBar")
1582 self:RegisterMessage("BigWigs_ResumeNameplateBar", "ResumeNameplateBar")
1583 self:RegisterMessage("BigWigs_StopBar", "StopSpecificBar")
1584 self:RegisterMessage("BigWigs_StopNameplateBar", "StopNameplateBar")
1585 self:RegisterMessage("BigWigs_StopBars", "StopModuleBars")
1586 self:RegisterMessage("BigWigs_OnBossDisable", "StopModuleBars")
1587 self:RegisterMessage("BigWigs_OnBossWipe", "StopModuleBars")
1588 self:RegisterMessage("BigWigs_OnPluginDisable", "StopModuleBars")
1589 self:RegisterMessage("BigWigs_StartConfigureMode", showAnchors)
1590 self:RegisterMessage("BigWigs_StopConfigureMode", hideAnchors)
1591 self:RegisterMessage("BigWigs_ResetPositions", resetAnchors)
1592 self:RegisterMessage("BigWigs_ProfileUpdate", updateProfile)
1593
1594 self:RefixClickIntercepts()
1595 self:RegisterEvent("MODIFIER_STATE_CHANGED", "RefixClickIntercepts")
1596
1597 -- Nameplate bars
1598 self:RegisterEvent("NAME_PLATE_UNIT_ADDED")
1599 self:RegisterEvent("NAME_PLATE_UNIT_REMOVED")
1600
1601 -- custom bars
1602 self:RegisterMessage("BigWigs_PluginComm")
1603 self:RegisterMessage("DBM_AddonMessage")
1604
1605 local tbl = BigWigs3DB.breakTime
1606 if tbl then -- Break time present, resume it
1607 local prevTime, seconds, nick, isDBM = tbl[1], tbl[2], tbl[3], tbl[4]
1608 local curTime = time()
1609 if curTime-prevTime > seconds then
1610 BigWigs3DB.breakTime = nil
1611 else
1612 startBreak(seconds-(curTime-prevTime), nick, isDBM, true)
1613 end
1614 end
1615end
1616
1617--------------------------------------------------------------------------------
1618-- Bar styles API
1619--
1620
1621do
1622 local currentAPIVersion = 1
1623 local errorWrongAPI = "The bar style API version is now %d; the bar style %q needs to be updated for this version of BigWigs."
1624 local errorMismatchedData = "The given style data does not seem to be a BigWigs bar styler."
1625 local errorAlreadyExist = "Trying to register %q as a bar styler, but it already exists."
1626 function plugin:RegisterBarStyle(key, styleData)
1627 if type(key) ~= "string" then error(errorMismatchedData) end
1628 if type(styleData) ~= "table" then error(errorMismatchedData) end
1629 if type(styleData.version) ~= "number" then error(errorMismatchedData) end
1630 if type(styleData.apiVersion) ~= "number" then error(errorMismatchedData) end
1631 if type(styleData.GetStyleName) ~= "function" then error(errorMismatchedData) end
1632 if styleData.apiVersion ~= currentAPIVersion then error(errorWrongAPI:format(currentAPIVersion, key)) end
1633 if barStyles[key] and barStyles[key].version == styleData.version then error(errorAlreadyExist:format(key)) end
1634 if not barStyles[key] or barStyles[key].version < styleData.version then
1635 barStyles[key] = styleData
1636 barStyleRegister[key] = styleData:GetStyleName()
1637 end
1638 end
1639end
1640
1641do
1642 local errorNoStyle = "BigWigs: No style with the ID %q has been registered. Reverting to default style."
1643 local function noop() end
1644 function plugin:SetBarStyle(style)
1645 if type(style) ~= "string" or not barStyles[style] then
1646 print(errorNoStyle:format(tostring(style)))
1647 style = "Default"
1648 end
1649 local newBarStyler = barStyles[style]
1650 if not newBarStyler.ApplyStyle then newBarStyler.ApplyStyle = noop end
1651 if not newBarStyler.BarStopped then newBarStyler.BarStopped = noop end
1652 if not newBarStyler.GetSpacing then newBarStyler.GetSpacing = noop end
1653 if not newBarStyler.OnEmphasize then newBarStyler.OnEmphasize = noop end
1654
1655 -- Iterate all running bars
1656 if currentBarStyler then
1657 if normalAnchor then
1658 for bar in next, normalAnchor.bars do
1659 currentBarStyler.BarStopped(bar)
1660 bar.candyBarBackdrop:Hide()
1661 newBarStyler.ApplyStyle(bar)
1662 end
1663 end
1664 if emphasizeAnchor then
1665 for bar in next, emphasizeAnchor.bars do
1666 currentBarStyler.BarStopped(bar)
1667 bar.candyBarBackdrop:Hide()
1668 newBarStyler.ApplyStyle(bar)
1669 end
1670 end
1671 end
1672 currentBarStyler = newBarStyler
1673
1674 rearrangeBars(normalAnchor)
1675 rearrangeBars(emphasizeAnchor)
1676
1677 if db then
1678 db.barStyle = style
1679 end
1680 end
1681end
1682
1683--------------------------------------------------------------------------------
1684-- Pausing bars
1685--
1686
1687function plugin:PauseBar(_, module, text)
1688 if not normalAnchor then return end
1689 for k in next, normalAnchor.bars do
1690 if k:Get("bigwigs:module") == module and k:GetLabel() == text then
1691 k:Pause()
1692 return
1693 end
1694 end
1695 for k in next, emphasizeAnchor.bars do
1696 if k:Get("bigwigs:module") == module and k:GetLabel() == text then
1697 k:Pause()
1698 return
1699 end
1700 end
1701end
1702
1703function plugin:PauseNameplateBar(_, module, text, unitGUID)
1704 local barInfo = nameplateBars[unitGUID] and nameplateBars[unitGUID][text]
1705 if barInfo and not barInfo.paused then
1706 barInfo.paused = true
1707 if barInfo.bar then
1708 barInfo.bar:Pause()
1709 else
1710 barInfo.deletionTimer:Cancel()
1711 end
1712 barInfo.remaining = barInfo.exp - GetTime()
1713 end
1714end
1715
1716function plugin:ResumeBar(_, module, text)
1717 if not normalAnchor then return end
1718 for k in next, normalAnchor.bars do
1719 if k:Get("bigwigs:module") == module and k:GetLabel() == text then
1720 k:Resume()
1721 return
1722 end
1723 end
1724 for k in next, emphasizeAnchor.bars do
1725 if k:Get("bigwigs:module") == module and k:GetLabel() == text then
1726 k:Resume()
1727 return
1728 end
1729 end
1730end
1731
1732function plugin:ResumeNameplateBar(_, module, text, unitGUID)
1733 local barInfo = nameplateBars[unitGUID] and nameplateBars[unitGUID][text]
1734 if barInfo and barInfo.paused then
1735 barInfo.paused = false
1736 barInfo.exp = GetTime() + barInfo.remaining
1737 if barInfo.bar then
1738 barInfo.bar:Resume()
1739 else
1740 barInfo.deletionTimer = createDeletionTimer(barInfo)
1741 end
1742 barInfo.remaining = nil
1743 end
1744end
1745
1746--------------------------------------------------------------------------------
1747-- Stopping bars
1748--
1749
1750function plugin:StopSpecificBar(_, module, text)
1751 if not normalAnchor then return end
1752 for k in next, normalAnchor.bars do
1753 if k:Get("bigwigs:module") == module and k:GetLabel() == text then
1754 k:Stop()
1755 end
1756 end
1757 for k in next, emphasizeAnchor.bars do
1758 if k:Get("bigwigs:module") == module and k:GetLabel() == text then
1759 k:Stop()
1760 end
1761 end
1762end
1763
1764function plugin:StopNameplateBar(_, module, text, guid)
1765 if not nameplateBars[guid] then return end
1766 local barInfo = nameplateBars[guid][text]
1767 if barInfo and barInfo.module == module then
1768 if barInfo.bar then
1769 barInfo.bar:Stop()
1770 else
1771 barInfo.deletionTimer:Cancel()
1772 nameplateCascadeDelete(guid, text)
1773 end
1774 end
1775end
1776
1777function plugin:StopModuleBars(_, module)
1778 if not normalAnchor then return end
1779 for k in next, normalAnchor.bars do
1780 if k:Get("bigwigs:module") == module then
1781 k:Stop()
1782 end
1783 end
1784 for k in next, emphasizeAnchor.bars do
1785 if k:Get("bigwigs:module") == module then
1786 k:Stop()
1787 end
1788 end
1789 for _, bars in next, nameplateBars do
1790 for _, barInfo in next, bars do
1791 if barInfo.module == module then
1792 if barInfo.bar then
1793 barInfo.bar:Stop()
1794 else
1795 barInfo.deletionTimer:Cancel()
1796 nameplateCascadeDelete(barInfo.unitGUID, barInfo.text)
1797 end
1798 end
1799 end
1800 end
1801end
1802
1803--------------------------------------------------------------------------------
1804-- Bar utility functions
1805--
1806
1807function plugin:GetBarTimeLeft(module, text)
1808 if normalAnchor then
1809 for k in next, normalAnchor.bars do
1810 if k:Get("bigwigs:module") == module and k:GetLabel() == text then
1811 return k.remaining
1812 end
1813 end
1814 for k in next, emphasizeAnchor.bars do
1815 if k:Get("bigwigs:module") == module and k:GetLabel() == text then
1816 return k.remaining
1817 end
1818 end
1819 end
1820 return 0
1821end
1822
1823function plugin:GetNameplateBarTimeLeft(module, text, guid)
1824 if nameplateBars[guid] then
1825 local barInfo = nameplateBars[guid][text]
1826 local bar = barInfo and barInfo.bar
1827 if bar and bar:Get("bigwigs:module") == module then
1828 return bar.remaining
1829 else
1830 return barInfo.paused and barInfo.remaining or barInfo.exp - GetTime()
1831 end
1832 end
1833 return 0
1834end
1835
1836--------------------------------------------------------------------------------
1837-- Clickable bars
1838--
1839
1840local function barClicked(bar, button)
1841 for action, enabled in next, plugin.db.profile[button] do
1842 if enabled then clickHandlers[action](bar) end
1843 end
1844end
1845
1846local function barOnEnter(bar)
1847 bar.candyBarBackground:SetVertexColor(1, 1, 1, 0.8)
1848end
1849local function barOnLeave(bar)
1850 local module = bar:Get("bigwigs:module")
1851 local key = bar:Get("bigwigs:option")
1852 bar.candyBarBackground:SetVertexColor(colors:GetColor("barBackground", module, key))
1853end
1854
1855local function refixClickOnBar(intercept, bar)
1856 if intercept then
1857 bar:EnableMouse(true)
1858 bar:SetScript("OnMouseDown", barClicked)
1859 bar:SetScript("OnEnter", barOnEnter)
1860 bar:SetScript("OnLeave", barOnLeave)
1861 else
1862 bar:EnableMouse(false)
1863 bar:SetScript("OnMouseDown", nil)
1864 bar:SetScript("OnEnter", nil)
1865 bar:SetScript("OnLeave", nil)
1866 end
1867end
1868local function refixClickOnAnchor(intercept, anchor)
1869 for bar in next, anchor.bars do
1870 if not intercept or bar:GetAlpha() > 0 then -- Don't enable for hidden bars
1871 refixClickOnBar(intercept, bar)
1872 end
1873 end
1874end
1875
1876do
1877 local keymap = {
1878 LALT = "ALT", RALT = "ALT",
1879 LSHIFT = "SHIFT", RSHIFT = "SHIFT",
1880 LCTRL = "CTRL", RCTRL = "CTRL",
1881 }
1882 function plugin:RefixClickIntercepts(event, key, state)
1883 if not db.interceptMouse or not normalAnchor then return end
1884 if not db.onlyInterceptOnKeypress or (db.onlyInterceptOnKeypress and type(key) == "string" and db.interceptKey == keymap[key] and state == 1) then
1885 refixClickOnAnchor(true, normalAnchor)
1886 refixClickOnAnchor(true, emphasizeAnchor)
1887 else
1888 refixClickOnAnchor(false, normalAnchor)
1889 refixClickOnAnchor(false, emphasizeAnchor)
1890 end
1891 end
1892end
1893
1894-- Super Emphasize the clicked bar
1895clickHandlers.emphasize = function(bar)
1896 -- Add 0.2sec here to catch messages for this option triggered when the bar ends.
1897 plugin:SendMessage("BigWigs_TempSuperEmphasize", bar:Get("bigwigs:module"), bar:Get("bigwigs:option"), bar:GetLabel(), bar.remaining)
1898end
1899
1900-- Report the bar status to the active group type (raid, party, solo)
1901do
1902 local tformat1 = "%d:%02d"
1903 local tformat2 = "%1.1f"
1904 local tformat3 = "%.0f"
1905 local function timeDetails(t)
1906 if t >= 3600 then -- > 1 hour
1907 local h = floor(t/3600)
1908 local m = t - (h*3600)
1909 return tformat1:format(h, m)
1910 elseif t >= 60 then -- 1 minute to 1 hour
1911 local m = floor(t/60)
1912 local s = t - (m*60)
1913 return tformat1:format(m, s)
1914 elseif t < 10 then -- 0 to 10 seconds
1915 return tformat2:format(t)
1916 else -- 10 seconds to one minute
1917 return tformat3:format(floor(t + .5))
1918 end
1919 end
1920 local SendChatMessage = BigWigsLoader.SendChatMessage
1921 clickHandlers.report = function(bar)
1922 local text = ("%s: %s"):format(bar:GetLabel(), timeDetails(bar.remaining))
1923 SendChatMessage(text, (IsInGroup(2) and "INSTANCE_CHAT") or (IsInRaid() and "RAID") or (IsInGroup() and "PARTY") or "SAY")
1924 end
1925end
1926
1927-- Removes the clicked bar
1928clickHandlers.remove = function(bar)
1929 plugin:SendMessage("BigWigs_SilenceOption", bar:Get("bigwigs:option"), bar.remaining + 0.3)
1930 bar:Stop()
1931end
1932
1933-- Removes all bars EXCEPT the clicked one
1934clickHandlers.removeOther = function(bar)
1935 if normalAnchor then
1936 for k in next, normalAnchor.bars do
1937 if k ~= bar then
1938 plugin:SendMessage("BigWigs_SilenceOption", k:Get("bigwigs:option"), k.remaining + 0.3)
1939 k:Stop()
1940 end
1941 end
1942 end
1943 if emphasizeAnchor then
1944 for k in next, emphasizeAnchor.bars do
1945 if k ~= bar then
1946 plugin:SendMessage("BigWigs_SilenceOption", k:Get("bigwigs:option"), k.remaining + 0.3)
1947 k:Stop()
1948 end
1949 end
1950 end
1951end
1952
1953-- Disables the option that launched this bar
1954clickHandlers.disable = function(bar)
1955 local m = bar:Get("bigwigs:module")
1956 if m and m.db and m.db.profile and bar:Get("bigwigs:option") then
1957 m.db.profile[bar:Get("bigwigs:option")] = 0
1958 end
1959end
1960
1961-----------------------------------------------------------------------
1962-- Start bars
1963--
1964
1965function plugin:CreateBar(module, key, text, time, icon, isApprox, unitGUID)
1966 local width, height
1967 if unitGUID then
1968 width, height = db.nameplateWidth, db.nameplateHeight
1969 if db.nameplateAutoWidth then
1970 local unit = findUnitByGUID(unitGUID)
1971 if unit then
1972 local nameplate = GetNamePlateForUnit(unit)
1973 width = nameplate:GetWidth()
1974 end
1975 end
1976 else
1977 width, height = db.BigWigsAnchor_width, db.BigWigsAnchor_height
1978 end
1979 local bar = candy:New(media:Fetch(STATUSBAR, db.texture), width, height)
1980 bar.candyBarBackground:SetVertexColor(colors:GetColor("barBackground", module, key))
1981 bar:Set("bigwigs:module", module)
1982 bar:Set("bigwigs:option", key)
1983 if unitGUID then
1984 bar:Set("bigwigs:unitGUID", unitGUID)
1985 else
1986 bar:Set("bigwigs:anchor", normalAnchor)
1987 normalAnchor.bars[bar] = true
1988 end
1989 bar:SetIcon(db.icon and icon or nil)
1990 bar:SetLabel(text)
1991 bar:SetDuration(time, isApprox)
1992 bar:SetColor(colors:GetColor("barColor", module, key))
1993 bar:SetTextColor(colors:GetColor("barText", module, key))
1994 bar:SetShadowColor(colors:GetColor("barTextShadow", module, key))
1995 bar.candyBarLabel:SetJustifyH(db.alignText)
1996 bar.candyBarDuration:SetJustifyH(db.alignTime)
1997 local flags = nil
1998 if db.monochrome and db.outline ~= "NONE" then
1999 flags = "MONOCHROME," .. db.outline
2000 elseif db.monochrome then
2001 flags = "MONOCHROME"
2002 elseif db.outline ~= "NONE" then
2003 flags = db.outline
2004 end
2005 local f = media:Fetch(FONT, db.fontName)
2006 bar.candyBarLabel:SetFont(f, db.fontSize, flags)
2007 bar.candyBarDuration:SetFont(f, db.fontSize, flags)
2008
2009 bar:SetTimeVisibility(db.time)
2010 bar:SetLabelVisibility(db.text)
2011 bar:SetIconPosition(db.iconPosition)
2012 bar:SetFill(db.fill)
2013
2014 if db.interceptMouse and not db.onlyInterceptOnKeypress and not unitGUID then
2015 refixClickOnBar(true, bar)
2016 end
2017
2018 return bar
2019end
2020
2021function plugin:BigWigs_StartBar(_, module, key, text, time, icon, isApprox)
2022 if not text then text = "" end
2023 self:StopSpecificBar(nil, module, text)
2024
2025 local bar = self:CreateBar(module, key, text, time, icon, isApprox)
2026 bar:Start()
2027 if db.emphasize and time < db.emphasizeTime then
2028 self:EmphasizeBar(bar, true)
2029 else
2030 currentBarStyler.ApplyStyle(bar)
2031 end
2032 rearrangeBars(bar:Get("bigwigs:anchor"))
2033
2034 self:SendMessage("BigWigs_BarCreated", self, bar, module, key, text, time, icon, isApprox)
2035 -- Check if :EmphasizeBar(bar) was run and trigger the callback.
2036 -- Bit of a roundabout method to approaching this so that we purposely keep callbacks firing last.
2037 if bar:Get("bigwigs:emphasized") then
2038 self:SendMessage("BigWigs_BarEmphasized", self, bar)
2039 end
2040end
2041
2042function plugin:BigWigs_StartNameplateBar(_, module, key, text, time, icon, isApprox, unitGUID)
2043 if not db.nameplateBars then return end
2044 if not text then text = "" end
2045 self:StopNameplateBar(nil, module, text, unitGUID)
2046
2047 if not nameplateBars[unitGUID] then nameplateBars[unitGUID] = {} end
2048 local barInfo = {
2049 module = module,
2050 key = key,
2051 text = text,
2052 time = time,
2053 exp = GetTime() + time,
2054 icon = icon,
2055 isApprox = isApprox,
2056 unitGUID = unitGUID,
2057 }
2058 nameplateBars[unitGUID][text] = barInfo
2059
2060 local unit = findUnitByGUID(unitGUID)
2061 if unit then
2062 local bar = self:CreateBar(module, key, text, time, icon, isApprox, unitGUID)
2063 barInfo.bar = bar
2064 bar:Start()
2065 if db.emphasize and time < db.emphasizeTime then
2066 self:EmphasizeBar(bar, true)
2067 else
2068 currentBarStyler.ApplyStyle(bar)
2069 end
2070 rearrangeNameplateBars(unitGUID)
2071 self:SendMessage("BigWigs_NameplateBarCreated", self, bar, module, key, text, time, icon, isApprox, unitGUID)
2072 -- Check if :EmphasizeBar(bar) was run and trigger the callback.
2073 -- Bit of a roundabout method to approaching this so that we purposely keep callbacks firing last.
2074 if bar:Get("bigwigs:emphasized") then
2075 self:SendMessage("BigWigs_BarEmphasized", self, bar)
2076 else
2077 nameplateEmpUpdate:Play()
2078 end
2079 else
2080 barInfo.deletionTimer = createDeletionTimer(barInfo)
2081 end
2082end
2083
2084--------------------------------------------------------------------------------
2085-- Emphasize
2086--
2087
2088do
2089 local dirty = nil
2090 local frame = CreateFrame("Frame")
2091 empUpdate = frame:CreateAnimationGroup()
2092 nameplateEmpUpdate = frame:CreateAnimationGroup()
2093 empUpdate:SetScript("OnLoop", function()
2094 for k in next, normalAnchor.bars do
2095 if k.remaining < db.emphasizeTime and not k:Get("bigwigs:emphasized") then
2096 dirty = true
2097 plugin:EmphasizeBar(k)
2098 plugin:SendMessage("BigWigs_BarEmphasized", plugin, k)
2099 end
2100 end
2101 if dirty then
2102 rearrangeBars(normalAnchor)
2103 rearrangeBars(emphasizeAnchor)
2104 dirty = nil
2105 end
2106 end)
2107 nameplateEmpUpdate:SetScript("OnLoop", function()
2108 for guid, bars in next, nameplateBars do
2109 for _, barInfo in next, bars do
2110 local bar = barInfo.bar
2111 if bar and bar.remaining < db.emphasizeTime and not bar:Get("bigwigs:emphasized") then
2112 plugin:EmphasizeBar(bar)
2113 rearrangeNameplateBars(bar:Get("bigwigs:unitGUID"))
2114 plugin:SendMessage("BigWigs_BarEmphasized", plugin, bar)
2115 end
2116 end
2117 end
2118 end)
2119 empUpdate:SetLooping("REPEAT")
2120 nameplateEmpUpdate:SetLooping("REPEAT")
2121
2122 local anim = empUpdate:CreateAnimation()
2123 anim:SetDuration(0.2)
2124 anim = nameplateEmpUpdate:CreateAnimation()
2125 anim:SetDuration(0.2)
2126end
2127
2128function plugin:EmphasizeBar(bar, start)
2129 local unitGUID = bar:Get("bigwigs:unitGUID")
2130 if db.emphasizeMove and not unitGUID then
2131 normalAnchor.bars[bar] = nil
2132 emphasizeAnchor.bars[bar] = true
2133 bar:Set("bigwigs:anchor", emphasizeAnchor)
2134 end
2135 currentBarStyler.BarStopped(bar)
2136 if not start and db.emphasizeRestart then
2137 bar:Start() -- restart the bar -> remaining time is a full length bar again after moving it to the emphasize anchor
2138 if unitGUID then
2139 nameplateBars[unitGUID][bar:GetLabel()].time = bar.remaining
2140 end
2141 end
2142 local module = bar:Get("bigwigs:module")
2143 local key = bar:Get("bigwigs:option")
2144
2145 local flags = nil
2146 if db.monochrome and db.outline ~= "NONE" then
2147 flags = "MONOCHROME," .. db.outline
2148 elseif db.monochrome then
2149 flags = "MONOCHROME"
2150 elseif db.outline ~= "NONE" then
2151 flags = db.outline
2152 end
2153 local f = media:Fetch(FONT, db.fontName)
2154 bar.candyBarLabel:SetFont(f, db.fontSizeEmph, flags)
2155 bar.candyBarDuration:SetFont(f, db.fontSizeEmph, flags)
2156
2157 bar:SetColor(colors:GetColor("barEmphasized", module, key))
2158 if unitGUID then
2159 bar:SetWidth(bar:GetWidth() * db.emphasizeMultiplier)
2160 bar:SetHeight(bar:GetHeight() * db.emphasizeMultiplier)
2161 else
2162 bar:SetHeight(db.BigWigsEmphasizeAnchor_height)
2163 bar:SetWidth(db.BigWigsEmphasizeAnchor_width)
2164 end
2165 currentBarStyler.ApplyStyle(bar)
2166 bar:Set("bigwigs:emphasized", true)
2167end
2168
2169--------------------------------------------------------------------------------
2170-- Custom Bars
2171--
2172
2173local function parseTime(input)
2174 if type(input) == "nil" then return end
2175 if tonumber(input) then return tonumber(input) end
2176 if type(input) == "string" then
2177 input = input:trim()
2178 if input:find(":") then
2179 local _, _, m, s = input:find("^(%d+):(%d+)$")
2180 if not tonumber(m) or not tonumber(s) then return end
2181 return (tonumber(m) * 60) + tonumber(s)
2182 elseif input:find("^%d+mi?n?$") then
2183 local _, _, t = input:find("^(%d+)mi?n?$")
2184 return tonumber(t) * 60
2185 end
2186 end
2187end
2188
2189local startCustomBar
2190do
2191 local timers, prevBars
2192 function startCustomBar(bar, nick, localOnly, isDBM)
2193 if not timers then timers, prevBars = {}, {} end
2194
2195 local seconds, barText
2196 if localOnly then
2197 seconds, barText, nick = bar, localOnly, L.localTimer
2198 else
2199 if prevBars[bar] and GetTime() - prevBars[bar] < 1.2 then return end -- Throttle
2200 prevBars[bar] = GetTime()
2201 if not UnitIsGroupLeader(nick) and not UnitIsGroupAssistant(nick) then return end
2202 seconds, barText = bar:match("(%S+) (.*)")
2203 seconds = parseTime(seconds)
2204 if type(seconds) ~= "number" or type(barText) ~= "string" or seconds < 0 then
2205 return
2206 end
2207 BigWigs:Print(L.customBarStarted:format(barText, isDBM and "DBM" or "BigWigs", nick))
2208 end
2209
2210 local id = "bwcb" .. nick .. barText
2211 if timers[id] then
2212 plugin:CancelTimer(timers[id])
2213 timers[id] = nil
2214 end
2215
2216 nick = nick:gsub("%-.+", "*") -- Remove server name
2217 if seconds == 0 then
2218 plugin:SendMessage("BigWigs_StopBar", plugin, nick..": "..barText)
2219 else
2220 timers[id] = plugin:ScheduleTimer("SendMessage", seconds, "BigWigs_Message", plugin, false, L.timerFinished:format(nick, barText), "yellow", 134376)
2221 plugin:SendMessage("BigWigs_StartBar", plugin, id, nick..": "..barText, seconds, 134376) -- 134376 = "Interface\\Icons\\INV_Misc_PocketWatch_01"
2222 end
2223 end
2224end
2225
2226do
2227 local timerTbl, lastBreak = nil, 0
2228 function startBreak(seconds, nick, isDBM, reboot)
2229 if not reboot then
2230 if (not UnitIsGroupLeader(nick) and not UnitIsGroupAssistant(nick) and not UnitIsUnit(nick, "player")) or IsEncounterInProgress() then return end
2231 seconds = tonumber(seconds)
2232 if not seconds or seconds < 0 or seconds > 3600 or (seconds > 0 and seconds < 60) then return end -- 1h max, 1m min
2233
2234 local t = GetTime()
2235 if t-lastBreak < 0.5 then return else lastBreak = t end -- Throttle
2236 end
2237
2238 if timerTbl then
2239 for i = 1, #timerTbl do
2240 plugin:CancelTimer(timerTbl[i])
2241 end
2242 if seconds == 0 then
2243 timerTbl = nil
2244 BigWigs3DB.breakTime = nil
2245 BigWigs:Print(L.breakStopped:format(nick))
2246 plugin:SendMessage("BigWigs_StopBar", plugin, L.breakBar)
2247 plugin:SendMessage("BigWigs_StopBreak", plugin, seconds, nick, isDBM, reboot)
2248 return
2249 end
2250 end
2251
2252 if not reboot then
2253 BigWigs3DB.breakTime = {time(), seconds, nick, isDBM}
2254 end
2255
2256 BigWigs:Print(L.breakStarted:format(isDBM and "DBM" or "BigWigs", nick))
2257
2258 timerTbl = {
2259 plugin:ScheduleTimer("SendMessage", seconds - 30, "BigWigs_Message", plugin, nil, L.breakSeconds:format(30), "orange", 134062), -- 134062 = "Interface\\Icons\\inv_misc_fork&knife"
2260 plugin:ScheduleTimer("SendMessage", seconds - 10, "BigWigs_Message", plugin, nil, L.breakSeconds:format(10), "orange", 134062),
2261 plugin:ScheduleTimer("SendMessage", seconds - 5, "BigWigs_Message", plugin, nil, L.breakSeconds:format(5), "orange", 134062),
2262 plugin:ScheduleTimer("SendMessage", seconds, "BigWigs_Message", plugin, nil, L.breakFinished, "red", 134062),
2263 plugin:ScheduleTimer("SendMessage", seconds, "BigWigs_Sound", plugin, nil, "Long"),
2264 plugin:ScheduleTimer(function() BigWigs3DB.breakTime = nil timerTbl = nil end, seconds)
2265 }
2266 if seconds > 119 then -- 2min
2267 timerTbl[#timerTbl+1] = plugin:ScheduleTimer("SendMessage", seconds - 60, "BigWigs_Message", plugin, nil, L.breakMinutes:format(1), "yellow", 134062)
2268 end
2269 if seconds > 239 then -- 4min
2270 local half = seconds / 2
2271 local m = half % 60
2272 local halfMin = (half - m) / 60
2273 timerTbl[#timerTbl+1] = plugin:ScheduleTimer("SendMessage", half + m, "BigWigs_Message", plugin, nil, L.breakMinutes:format(halfMin), "yellow", 134062)
2274 end
2275
2276 plugin:SendMessage("BigWigs_Message", plugin, nil, L.breakMinutes:format(seconds/60), "green", 134062)
2277 plugin:SendMessage("BigWigs_Sound", plugin, nil, "Long")
2278 plugin:SendMessage("BigWigs_StartBar", plugin, nil, L.breakBar, seconds, 134062)
2279 plugin:SendMessage("BigWigs_StartBreak", plugin, seconds, nick, isDBM, reboot)
2280 end
2281end
2282
2283function plugin:DBM_AddonMessage(_, sender, prefix, seconds, text)
2284 if prefix == "U" then
2285 startCustomBar(seconds.." "..text, sender, nil, true)
2286 elseif prefix == "BT" then
2287 startBreak(seconds, sender, true)
2288 end
2289end
2290
2291function plugin:BigWigs_PluginComm(_, msg, seconds, sender)
2292 if seconds then
2293 if msg == "CBar" then
2294 startCustomBar(seconds, sender)
2295 elseif msg == "Break" then
2296 startBreak(seconds, sender)
2297 end
2298 end
2299end
2300
2301-------------------------------------------------------------------------------
2302-- Nameplate bar management
2303--
2304
2305function plugin:NAME_PLATE_UNIT_ADDED(_, unit)
2306 local guid = UnitGUID(unit)
2307 local unitBars = nameplateBars[guid]
2308 if not unitBars then return end
2309 for _, barInfo in next, unitBars do
2310 local width, height = db.nameplateWidth, db.nameplateHeight
2311 if db.nameplateAutoWidth then
2312 local nameplate = GetNamePlateForUnit(unit)
2313 width = nameplate:GetWidth()
2314 end
2315 local time = barInfo.paused and barInfo.remaining or barInfo.exp - GetTime()
2316 local bar = plugin:CreateBar(
2317 barInfo.module,
2318 barInfo.key,
2319 barInfo.text,
2320 time,
2321 barInfo.icon,
2322 barInfo.isApprox,
2323 barInfo.unitGUID
2324 )
2325 bar:SetSize(width, height)
2326 barInfo.bar = bar
2327 barInfo.deletionTimer:Cancel()
2328 barInfo.deletionTimer = nil
2329 bar:Start(barInfo.time)
2330 if barInfo.paused then
2331 bar:Pause()
2332 end
2333 end
2334 rearrangeNameplateBars(guid)
2335end
2336
2337function plugin:NAME_PLATE_UNIT_REMOVED(_, unit)
2338 local guid = UnitGUID(unit)
2339 local unitBars = nameplateBars[guid]
2340 if not unitBars then return end
2341
2342 for _, barInfo in next, unitBars do
2343 barInfo.bar:Set("bigwigs:offscreen", true)
2344 barInfo.bar:Stop()
2345 if not barInfo.paused then
2346 barInfo.deletionTimer = createDeletionTimer(barInfo)
2347 end
2348 end
2349end
2350
2351-------------------------------------------------------------------------------
2352-- Slashcommand
2353--
2354
2355local SendAddonMessage = BigWigsLoader.SendAddonMessage
2356do
2357 local times
2358 SlashCmdList.BIGWIGSRAIDBAR = function(input)
2359 if not plugin:IsEnabled() then BigWigs:Enable() end
2360
2361 if not IsInGroup() or (not UnitIsGroupLeader("player") and not UnitIsGroupAssistant("player")) then BigWigs:Print(L.requiresLeadOrAssist) return end
2362
2363 local seconds, barText = input:match("(%S+) (.*)")
2364 if not seconds or not barText then BigWigs:Print(L.wrongCustomBarFormat) return end
2365
2366 seconds = parseTime(seconds)
2367 if not seconds or seconds < 0 then BigWigs:Print(L.wrongTime) return end
2368
2369 if not times then times = {} end
2370 local t = GetTime()
2371 if not times[input] or (times[input] and (times[input] + 2) < t) then
2372 times[input] = t
2373 BigWigs:Print(L.sendCustomBar:format(barText))
2374 plugin:Sync("CBar", input)
2375 SendAddonMessage("D4", ("U\t%d\t%s"):format(seconds, barText), IsInGroup(2) and "INSTANCE_CHAT" or "RAID") -- DBM message
2376 end
2377 end
2378 SLASH_BIGWIGSRAIDBAR1 = "/raidbar"
2379end
2380
2381SlashCmdList.BIGWIGSLOCALBAR = function(input)
2382 if not plugin:IsEnabled() then BigWigs:Enable() end
2383
2384 local seconds, barText = input:match("(%S+) (.*)")
2385 if not seconds or not barText then BigWigs:Print(L.wrongCustomBarFormat:gsub("/raidbar", "/localbar")) return end
2386
2387 seconds = parseTime(seconds)
2388 if not seconds then BigWigs:Print(L.wrongTime) return end
2389
2390 startCustomBar(seconds, plugin:UnitName("player"), barText)
2391end
2392SLASH_BIGWIGSLOCALBAR1 = "/localbar"
2393
2394SlashCmdList.BIGWIGSBREAK = function(input)
2395 if not plugin:IsEnabled() then BigWigs:Enable() end
2396 if IsEncounterInProgress() then BigWigs:Print(L.encounterRestricted) return end -- Doesn't make sense to allow this in combat
2397 if not IsInGroup() or UnitIsGroupLeader("player") or UnitIsGroupAssistant("player") then -- Solo or leader/assist
2398 local minutes = tonumber(input)
2399 if not minutes or minutes < 0 or minutes > 60 or (minutes > 0 and minutes < 1) then BigWigs:Print(L.wrongBreakFormat) return end -- 1h max, 1m min
2400
2401 if minutes ~= 0 then
2402 BigWigs:Print(L.sendBreak)
2403 end
2404 local seconds = minutes * 60
2405 plugin:Sync("Break", seconds)
2406
2407 if IsInGroup() then
2408 SendAddonMessage("D4", ("BT\t%d"):format(seconds), IsInGroup(2) and "INSTANCE_CHAT" or "RAID") -- DBM message
2409 end
2410 else
2411 BigWigs:Print(L.requiresLeadOrAssist)
2412 end
2413end
2414SLASH_BIGWIGSBREAK1 = "/break"