| 
arkanes@0
 | 
     1 local _, kbf = ...
 | 
| 
arkanes@0
 | 
     2 
 | 
| 
arkanes@0
 | 
     3 KBF = kbf -- make global for debugging
 | 
| 
arkanes@0
 | 
     4 
 | 
| 
arkanes@0
 | 
     5 local kbf = LibStub("AceAddon-3.0"):NewAddon(kbf, "KBF", "AceEvent-3.0", "AceConsole-3.0")
 | 
| 
arkanes@0
 | 
     6 
 | 
| 
arkanes@0
 | 
     7 
 | 
| 
arkanes@0
 | 
     8 function kbf:OnInitialize()
 | 
| 
arkanes@0
 | 
     9     self.options = {
 | 
| 
arkanes@0
 | 
    10         barWidth = 200 + 16 + 8,
 | 
| 
arkanes@0
 | 
    11         barHeight = 16 + 8
 | 
| 
arkanes@0
 | 
    12     }
 | 
| 
arkanes@0
 | 
    13     self.anchor = self:CreateAnchorFrame()
 | 
| 
arkanes@2
 | 
    14     self.buffBars = {}
 | 
| 
arkanes@0
 | 
    15     self.anchor:Show()
 | 
| 
arkanes@0
 | 
    16     self:RegisterEvent("UNIT_AURA")
 | 
| 
arkanes@4
 | 
    17     -- set up the countdown timer
 | 
| 
arkanes@4
 | 
    18     -- TODO: Fancy enable/disable based on whether you have any timed buffs.
 | 
| 
arkanes@4
 | 
    19     -- Not a big deal, how often do you care about that
 | 
| 
arkanes@4
 | 
    20     self.anchor:SetScript("OnUpdate", function() self:OnUpdate() end)
 | 
| 
arkanes@0
 | 
    21 end
 | 
| 
arkanes@1
 | 
    22 -- naming convention
 | 
| 
arkanes@1
 | 
    23 -- "frame" is the secure aura button created by the group handler
 | 
| 
arkanes@1
 | 
    24 -- "bar" is the set of icon + status bars that we create to show the buff time
 | 
| 
arkanes@0
 | 
    25 
 | 
| 
arkanes@4
 | 
    26 function kbf:OnUpdate()
 | 
| 
arkanes@4
 | 
    27     for idx=1,99 do
 | 
| 
arkanes@4
 | 
    28         local frame = self.secureFrame:GetAttribute("child"..idx)
 | 
| 
arkanes@4
 | 
    29         if not (frame and frame.expirationTime) then break end
 | 
| 
arkanes@4
 | 
    30         local remaining = frame.expirationTime - GetTime()
 | 
| 
arkanes@4
 | 
    31         remaining = math.max(0, remaining)
 | 
| 
arkanes@4
 | 
    32         local perc = remaining / frame.duration
 | 
| 
arkanes@4
 | 
    33         frame.timertext:SetText(self:FormatTimeText(remaining))
 | 
| 
arkanes@4
 | 
    34         frame.statusbar:SetValue(remaining)
 | 
| 
arkanes@4
 | 
    35     end
 | 
| 
arkanes@4
 | 
    36 end
 | 
| 
arkanes@4
 | 
    37 
 | 
| 
arkanes@0
 | 
    38 function kbf:UNIT_AURA(event, unit)
 | 
| 
arkanes@2
 | 
    39     if unit ~= self.secureFrame:GetAttribute("unit") then return end
 | 
| 
arkanes@2
 | 
    40     for idx=1,99 do
 | 
| 
arkanes@0
 | 
    41         local frame = self.secureFrame:GetAttribute("child"..idx)
 | 
| 
arkanes@0
 | 
    42         if not frame then break end
 | 
| 
arkanes@3
 | 
    43         self:BindBarToBuff(frame, unit)
 | 
| 
arkanes@0
 | 
    44     end
 | 
| 
arkanes@0
 | 
    45 end
 | 
| 
arkanes@0
 | 
    46 
 | 
| 
arkanes@3
 | 
    47 function kbf:BindBarToBuff(parentFrame, unit)
 | 
| 
arkanes@3
 | 
    48     local index = parentFrame:GetAttribute("index")
 | 
| 
arkanes@3
 | 
    49     local filter = parentFrame:GetAttribute("filter")
 | 
| 
arkanes@0
 | 
    50     local name, rank, icon, count, debuffType, duration, expirationTime, 
 | 
| 
arkanes@3
 | 
    51         unitCaster, isStealable, shouldConsolidate, spellId = UnitAura(unit, index, filter)
 | 
| 
arkanes@2
 | 
    52     if not parentFrame.icon then
 | 
| 
arkanes@2
 | 
    53         self:ConstructBar(parentFrame)
 | 
| 
arkanes@0
 | 
    54     end
 | 
| 
arkanes@2
 | 
    55     parentFrame.icon:SetNormalTexture(icon)
 | 
| 
arkanes@0
 | 
    56     if stacks and stacks > 0 then
 | 
| 
arkanes@2
 | 
    57         parentFrame.text:SetText(string.format("%s(%d)", name, stacks))
 | 
| 
arkanes@0
 | 
    58     else
 | 
| 
arkanes@2
 | 
    59         parentFrame.text:SetText(name)
 | 
| 
arkanes@0
 | 
    60     end
 | 
| 
arkanes@4
 | 
    61     parentFrame.timertext:SetText(self:FormatTimeText(duration))
 | 
| 
arkanes@4
 | 
    62     -- store duration information
 | 
| 
arkanes@4
 | 
    63     if duration > 0 then
 | 
| 
arkanes@4
 | 
    64         parentFrame.expirationTime = expirationTime
 | 
| 
arkanes@4
 | 
    65         parentFrame.duration = duration
 | 
| 
arkanes@4
 | 
    66         parentFrame.statusbar:SetMinMaxValues(0, duration)
 | 
| 
arkanes@4
 | 
    67         parentFrame.statusbar:SetValue(duration)
 | 
| 
arkanes@4
 | 
    68     else
 | 
| 
arkanes@4
 | 
    69         parentFrame.expirationTime = nil
 | 
| 
arkanes@4
 | 
    70         parentFrame.duration = 0
 | 
| 
arkanes@4
 | 
    71         parentFrame.statusbar:SetMinMaxValues(0,1)
 | 
| 
arkanes@4
 | 
    72         parentFrame.statusbar:SetValue(1)
 | 
| 
arkanes@4
 | 
    73     end
 | 
| 
arkanes@4
 | 
    74 end
 | 
| 
arkanes@4
 | 
    75 
 | 
| 
arkanes@4
 | 
    76 function kbf:FormatTimeText(time)
 | 
| 
arkanes@4
 | 
    77     if not time or time == 0 then return "" end
 | 
| 
arkanes@4
 | 
    78     local timetext
 | 
| 
arkanes@4
 | 
    79     local h = floor(time/3600)
 | 
| 
arkanes@4
 | 
    80     local m = time - (h*3600)
 | 
| 
arkanes@4
 | 
    81     m = floor(m/60)
 | 
| 
arkanes@4
 | 
    82     local s = time - ((h*3600) + (m*60))
 | 
| 
arkanes@4
 | 
    83     if h > 0 then
 | 
| 
arkanes@4
 | 
    84         timetext = ("%d:%02d"):format(h, m)
 | 
| 
arkanes@4
 | 
    85     elseif m > 0 then
 | 
| 
arkanes@4
 | 
    86         timetext = string.format("%d:%02d", m, floor(s))
 | 
| 
arkanes@4
 | 
    87     elseif s < 10 then
 | 
| 
arkanes@4
 | 
    88         timetext = string.format("%1.1f", s)
 | 
| 
arkanes@4
 | 
    89     else
 | 
| 
arkanes@4
 | 
    90         timetext = string.format("%.0f", floor(s))
 | 
| 
arkanes@4
 | 
    91     end
 | 
| 
arkanes@4
 | 
    92     return timetext
 | 
| 
arkanes@0
 | 
    93 end
 | 
| 
arkanes@0
 | 
    94 
 | 
| 
arkanes@1
 | 
    95 -- creates a icon + statusbar bar
 | 
| 
arkanes@1
 | 
    96 function kbf:ConstructBar(frame)
 | 
| 
arkanes@0
 | 
    97     local texture = "Interface\\TargetingFrame\\UI-StatusBar"
 | 
| 
arkanes@1
 | 
    98     -- Because of secureframe suckiness, these height & width numbers
 | 
| 
arkanes@1
 | 
    99     -- have to be consistent with the stuff in KBF.xml
 | 
| 
arkanes@0
 | 
   100     local height = 16
 | 
| 
arkanes@1
 | 
   101     local width = 200 -- this is the width *without* the icon
 | 
| 
arkanes@0
 | 
   102     local font, _ style = GameFontHighlight:GetFont()
 | 
| 
arkanes@0
 | 
   103     local bgcolor = {1, 0, 0, 0.5}
 | 
| 
arkanes@0
 | 
   104     local color = {0, 1, 0, 1}
 | 
| 
arkanes@0
 | 
   105     local fontsize = 11
 | 
| 
arkanes@0
 | 
   106     local timertextwidth = fontsize * 3.6
 | 
| 
arkanes@0
 | 
   107     local textcolor = {1, 1, 1, 1}
 | 
| 
arkanes@0
 | 
   108     local timertextcolor = {1, 1, 1, 1}
 | 
| 
arkanes@1
 | 
   109     --local bar = CreateFrame("Button", nil, UIParent) -- the "top level" frame that represents the bar as a whole
 | 
| 
arkanes@1
 | 
   110     local bar = frame
 | 
| 
arkanes@0
 | 
   111     bar.icon = CreateFrame("Button", nil, bar) -- the icon
 | 
| 
arkanes@0
 | 
   112     bar.statusbarbg = CreateFrame("StatusBar", nil, bar) -- the bars background
 | 
| 
arkanes@0
 | 
   113     bar.statusbar = CreateFrame("StatusBar", nil, bar) -- and the bars foreground
 | 
| 
arkanes@0
 | 
   114     bar.text = bar.statusbar:CreateFontString(nil, "OVERLAY") -- the label text
 | 
| 
arkanes@0
 | 
   115     bar.timertext = bar.statusbar:CreateFontString(nil, "OVERLAY") -- and the timer text
 | 
| 
arkanes@0
 | 
   116 
 | 
| 
arkanes@0
 | 
   117     -- the icon
 | 
| 
arkanes@0
 | 
   118     bar.icon:ClearAllPoints()
 | 
| 
arkanes@0
 | 
   119     bar.icon:SetPoint("LEFT", bar, "LEFT", 0, 0)
 | 
| 
arkanes@0
 | 
   120     -- icons are square
 | 
| 
arkanes@0
 | 
   121     bar.icon:SetWidth(height)
 | 
| 
arkanes@0
 | 
   122     bar.icon:SetHeight(height)
 | 
| 
arkanes@2
 | 
   123     --bar.icon:EnableMouse(false)
 | 
| 
arkanes@0
 | 
   124     -- the status bar background & foreground
 | 
| 
arkanes@0
 | 
   125     local function setupStatusBar(sb, color)
 | 
| 
arkanes@0
 | 
   126         sb:ClearAllPoints()
 | 
| 
arkanes@0
 | 
   127         sb:SetHeight(height)
 | 
| 
arkanes@0
 | 
   128         sb:SetWidth(width)
 | 
| 
arkanes@0
 | 
   129         -- offset the height of the frame on the x-axis for the icon.
 | 
| 
arkanes@0
 | 
   130         sb:SetPoint("TOPLEFT", bar, "TOPLEFT", height, 0)
 | 
| 
arkanes@0
 | 
   131         sb:SetStatusBarTexture(texture)
 | 
| 
arkanes@0
 | 
   132         sb:GetStatusBarTexture():SetVertTile(false)
 | 
| 
arkanes@0
 | 
   133         sb:GetStatusBarTexture():SetHorizTile(false)
 | 
| 
arkanes@0
 | 
   134         sb:SetStatusBarColor(unpack(color))
 | 
| 
arkanes@0
 | 
   135         sb:SetMinMaxValues(0,1)
 | 
| 
arkanes@0
 | 
   136         sb:SetValue(1)
 | 
| 
arkanes@0
 | 
   137     end
 | 
| 
arkanes@0
 | 
   138     setupStatusBar(bar.statusbarbg, bgcolor)
 | 
| 
arkanes@0
 | 
   139     setupStatusBar(bar.statusbar, color)
 | 
| 
arkanes@0
 | 
   140     bar.statusbarbg:SetFrameLevel(bar.statusbarbg:GetFrameLevel()-1) -- make sure the bg frame stays in the back
 | 
| 
arkanes@0
 | 
   141     -- timer text
 | 
| 
arkanes@0
 | 
   142     bar.timertext:SetFontObject(GameFontHighlight)
 | 
| 
arkanes@0
 | 
   143     bar.timertext:SetFont(GameFontHighlight:GetFont())
 | 
| 
arkanes@0
 | 
   144     bar.timertext:SetHeight(height)
 | 
| 
arkanes@0
 | 
   145     bar.timertext:SetWidth(timertextwidth)
 | 
| 
arkanes@0
 | 
   146     bar.timertext:SetPoint("LEFT", bar.statusbar, "LEFT", 0, 0)
 | 
| 
arkanes@0
 | 
   147     bar.timertext:SetJustifyH("RIGHT")
 | 
| 
arkanes@0
 | 
   148     bar.timertext:SetText("time")
 | 
| 
arkanes@0
 | 
   149     bar.timertext:SetTextColor(timertextcolor[1], timertextcolor[2], timertextcolor[3], timertextcolor[4])
 | 
| 
arkanes@0
 | 
   150 
 | 
| 
arkanes@0
 | 
   151     -- and the label text
 | 
| 
arkanes@0
 | 
   152     bar.text:SetFontObject(GameFontHighlight)
 | 
| 
arkanes@0
 | 
   153     bar.text:SetFont(GameFontHighlight:GetFont())
 | 
| 
arkanes@0
 | 
   154     bar.text:SetHeight(height)
 | 
| 
arkanes@0
 | 
   155     bar.text:SetWidth((width - timertextwidth) *.9)
 | 
| 
arkanes@0
 | 
   156     bar.text:SetPoint("RIGHT", bar.statusbar, "RIGHT", 0, 0)
 | 
| 
arkanes@0
 | 
   157     bar.text:SetJustifyH("LEFT")
 | 
| 
arkanes@0
 | 
   158     bar.text:SetText("text")
 | 
| 
arkanes@0
 | 
   159     bar.text:SetTextColor(textcolor[1], textcolor[2], textcolor[3], textcolor[4])
 | 
| 
arkanes@0
 | 
   160 
 | 
| 
arkanes@0
 | 
   161     bar:EnableMouse(true)
 | 
| 
arkanes@0
 | 
   162     return bar
 | 
| 
arkanes@0
 | 
   163 end
 | 
| 
arkanes@0
 | 
   164 
 | 
| 
arkanes@0
 | 
   165 function kbf:CreateAnchorFrame()
 | 
| 
arkanes@0
 | 
   166     -- give it a name so it'll remember its position
 | 
| 
arkanes@0
 | 
   167     local anchor = CreateFrame("FRAME", "KBFAnchorFrame", UIParent)
 | 
| 
arkanes@0
 | 
   168     anchor:SetClampedToScreen(true)
 | 
| 
arkanes@0
 | 
   169     anchor:SetBackdrop({bgFile = "Interface/Tooltips/UI-Tooltip-Background", 
 | 
| 
arkanes@0
 | 
   170                          edgeFile = "Interface/Tooltips/UI-Tooltip-Border", 
 | 
| 
arkanes@0
 | 
   171                          tile = true, tileSize = 16, edgeSize = 16,
 | 
| 
arkanes@0
 | 
   172                          insets = { left = 4, right = 4, top = 4, bottom = 4 },
 | 
| 
arkanes@0
 | 
   173                          })
 | 
| 
arkanes@0
 | 
   174     local text = anchor:CreateFontString(nil, "OVERLAY") -- the label text
 | 
| 
arkanes@0
 | 
   175     text:SetFontObject(GameFontHighlight)
 | 
| 
arkanes@0
 | 
   176     text:SetFont(GameFontHighlight:GetFont())
 | 
| 
arkanes@0
 | 
   177     text:SetPoint("TOPLEFT", anchor, "TOPLEFT", 0, 0)
 | 
| 
arkanes@0
 | 
   178     text:SetPoint("BOTTOMRIGHT", anchor, "BOTTOMRIGHT", 0, 0)
 | 
| 
arkanes@0
 | 
   179     text:SetText("KBF ANCHOR")
 | 
| 
arkanes@0
 | 
   180     anchor:SetWidth(self.options.barWidth)
 | 
| 
arkanes@0
 | 
   181     anchor:SetHeight(self.options.barHeight)
 | 
| 
arkanes@0
 | 
   182     -- movability
 | 
| 
arkanes@0
 | 
   183     anchor:EnableMouse(true)
 | 
| 
arkanes@0
 | 
   184     anchor:SetMovable(true)
 | 
| 
arkanes@0
 | 
   185     anchor:RegisterForDrag("LeftButton")
 | 
| 
arkanes@0
 | 
   186     anchor:SetScript("OnDragStart", anchor.StartMoving)
 | 
| 
arkanes@0
 | 
   187     anchor:SetScript("OnDragStop",  anchor.StopMovingOrSizing)
 | 
| 
arkanes@0
 | 
   188     anchor:ClearAllPoints()
 | 
| 
arkanes@0
 | 
   189     anchor:SetPoint("CENTER", UIParent, "CENTER", 0, 0)
 | 
| 
arkanes@0
 | 
   190     anchor:Hide()
 | 
| 
arkanes@0
 | 
   191     
 | 
| 
arkanes@0
 | 
   192     local frame = CreateFrame("FRAME", "KBFBuffFrame", anchor, "SecureAuraHeaderTemplate")
 | 
| 
arkanes@0
 | 
   193     --local frame = anchor
 | 
| 
arkanes@0
 | 
   194     frame:SetAttribute("filter", "HELPFUL")
 | 
| 
arkanes@0
 | 
   195     frame:SetAttribute("template", "KBFSecureUnitAuraTemplate")
 | 
| 
arkanes@3
 | 
   196     frame:SetAttribute("point", "TOP")
 | 
| 
arkanes@0
 | 
   197     frame:SetAttribute("wrapAfter", 100) -- required due to bugs in secure header
 | 
| 
arkanes@0
 | 
   198     frame:SetAttribute("consolidateTo", nil)
 | 
| 
arkanes@0
 | 
   199     --frame:SetAttribute("wrapXOffset", 0)
 | 
| 
arkanes@0
 | 
   200     --frame:SetAttribute("wrapYOffset", -34)
 | 
| 
arkanes@2
 | 
   201     frame:SetAttribute("xOffset", 0)
 | 
| 
arkanes@3
 | 
   202     frame:SetAttribute("yOffset", -16)
 | 
| 
arkanes@3
 | 
   203     frame:SetAttribute("minWidth",  216)
 | 
| 
arkanes@3
 | 
   204     frame:SetAttribute("minHeight", 16)
 | 
| 
arkanes@2
 | 
   205     frame:SetAttribute("unit", "player") -- TODO: figure out the vehicle swapping stuff
 | 
| 
arkanes@3
 | 
   206     frame:SetAttribute("sortMethod", "NAME")
 | 
| 
arkanes@3
 | 
   207     frame:SetAttribute("sortOrder", "-")
 | 
| 
arkanes@3
 | 
   208     frame:SetPoint("TOP", anchor, "BOTTOM", 0, 0)
 | 
| 
arkanes@5
 | 
   209 --   frame:SetBackdrop({bgFile = "Interface/Tooltips/UI-Tooltip-Background", 
 | 
| 
arkanes@5
 | 
   210 --                        edgeFile = "Interface/Tooltips/UI-Tooltip-Border", 
 | 
| 
arkanes@5
 | 
   211 --                        tile = true, tileSize = 16, edgeSize = 16,
 | 
| 
arkanes@5
 | 
   212 --                        insets = { left = 4, right = 4, top = 4, bottom = 4 },
 | 
| 
arkanes@5
 | 
   213 --                        })
 | 
| 
arkanes@5
 | 
   214     frame:Show() -- has to be shown, otherwise the child frames don't show
 | 
| 
arkanes@0
 | 
   215     self.secureFrame = frame
 | 
| 
arkanes@0
 | 
   216     return anchor
 | 
| 
arkanes@0
 | 
   217 end
 |