Quantcast
WoWInterface: SVN - fernir_UI - Rev 2 - /oUF/elements/aura.lua

WoWInterface SVN fernir_UI

[/] [oUF/] [elements/] [aura.lua] - Rev 2

Compare with Previous | Blame | View Log

--[[
        Elements handled: .Auras, .Buffs, .Debuffs

        Shared:
         - spacing: Padding between aura icons. (Default: 0)
         - size: Size of the aura icons. (Default: 16)
         - initialAnchor: Initial anchor in the aura frame. (Default: "BOTTOMLEFT")
         - onlyShowPlayer: Only display icons casted by the player. (Default: nil)
         - growth-x: Growth direction, affected by initialAnchor. (Default: "UP")
         - growth-y: Growth direction, affected by initialAnchor. (Default: "RIGHT")
         - disableCooldown: Disable the Cooldown Spiral on the Aura Icons. (Default: nil)
         - filter: Expects a string with filter. See the UnitAura[1] documentation for
                more information.

        .Auras only:
         - gap: Adds a empty icon to separate buffs and debuffs. (Default: nil)
         - numBuffs: The maximum number of buffs that should be shown. (Default: 32)
         - numDebuffs: The maximum number of debuffs that should be shown. (Default: 40)
         - buffFilter: See filter on Shared. (Default: "HELPFUL")
         - debuffFilter: See filter on Shared. (Default: "HARMFUL")
         - Variables set by .Auras:
                 - visibleBuffs: Number of currently visible buff icons.
                 - visibleDebuffs: Number of currently visible debuff icons.
                 - visibleAuras: Total number of currently visible buffs + debuffs.

        .Buffs only:
         - num: The maximum number of buffs that should be shown. (Default: 32)
         - Variables set by .Buffs:
                 - visibleBuffs: Number of currently visible buff icons.

        .Debuffs only:
         - num: The maximum number of debuffs that should be shown. (Default: 40)
         - Variables set by .Debuffs:
                 - visibleDebuffs: Number of currently visible debuff icons.

        Functions that can be overridden from within a layout:
         - :PostCreateAuraIcon(icon, icons, index, isDebuff)
         - :CreateAuraIcon(icons, index, isDebuff)
         - :PostUpdateAuraIcon(icons, unit, icon, index, offset, filter, isDebuff)
         - :PreUpdateAura(event, unit)
         - :PreAuraSetPosition(auras, max)
         - :SetAuraPosition(auras, max)
         - :PostUpdateAura(event, unit)

        [1] http://www.wowwiki.com/API_UnitAura
--]]
local parent, ns = ...
local oUF = ns.oUF

local OnEnter = function(self)
        if(not self:IsVisible()) then return end

        GameTooltip:SetOwner(self, "ANCHOR_BOTTOMRIGHT")
        GameTooltip:SetUnitAura(self.frame.unit, self:GetID(), self.filter)
end

local OnLeave = function()
        GameTooltip:Hide()
end

-- We don't really need to validate much here as the filter should prevent us
-- from doing something we shouldn't.
local OnClick = function(self)
        CancelUnitBuff(self.frame.unit, self:GetID(), self.filter)
end

local createAuraIcon = function(self, icons, index, debuff)
        local button = CreateFrame("Button", nil, icons)
        button:EnableMouse(true)
        button:RegisterForClicks'RightButtonUp'

        button:SetWidth(icons.size or 16)
        button:SetHeight(icons.size or 16)

        local cd = CreateFrame("Cooldown", nil, button)
        cd:SetAllPoints(button)

        local icon = button:CreateTexture(nil, "BACKGROUND")
        icon:SetAllPoints(button)

        local count = button:CreateFontString(nil, "OVERLAY")
        count:SetFontObject(NumberFontNormal)
        count:SetPoint("BOTTOMRIGHT", button, "BOTTOMRIGHT", -1, 0)

        local overlay = button:CreateTexture(nil, "OVERLAY")
        overlay:SetTexture"Interface\\Buttons\\UI-Debuff-Overlays"
        overlay:SetAllPoints(button)
        overlay:SetTexCoord(.296875, .5703125, 0, .515625)
        button.overlay = overlay

        button:SetScript("OnEnter", OnEnter)
        button:SetScript("OnLeave", OnLeave)

        if(self.unit == 'player') then
                button:SetScript('OnClick', OnClick)
        end

        table.insert(icons, button)

        button.parent = icons
        button.frame = self
        button.debuff = debuff

        button.icon = icon
        button.count = count
        button.cd = cd

        if(self.PostCreateAuraIcon) then self:PostCreateAuraIcon(button, icons, index, debuff) end

        return button
end

local customFilter = function(icons, unit, icon, name, rank, texture, count, dtype, duration, timeLeft, caster)
        local isPlayer

        if(caster == 'player' or caster == 'vehicle') then
                isPlayer = true
        end

        if((icons.onlyShowPlayer and isPlayer) or (not icons.onlyShowPlayer and name)) then
                icon.isPlayer = isPlayer
                icon.owner = caster
                return true
        end
end

local updateIcon = function(self, unit, icons, index, offset, filter, isDebuff, max)
        if(index == 0) then index = max end

        local name, rank, texture, count, dtype, duration, timeLeft, caster, isStealable, shouldConsolidate, spellID = UnitAura(unit, index, filter)
        if(name) then
                local icon = icons[index + offset]
                if(not icon) then
                        icon = (self.CreateAuraIcon or createAuraIcon) (self, icons, index, isDebuff)
                end

                local show = (self.CustomAuraFilter or customFilter) (icons, unit, icon, name, rank, texture, count, dtype, duration, timeLeft, caster, isStealable, shouldConsolidate, spellID)
                if(show) then
                        -- We might want to consider delaying the creation of an actual cooldown
                        -- object to this point, but I think that will just make things needlessly
                        -- complicated.
                        local cd = icon.cd
                        if(cd and not icons.disableCooldown) then
                                if(duration and duration > 0) then
                                        cd:SetCooldown(timeLeft - duration, duration)
                                        cd:Show()
                                else
                                        cd:Hide()
                                end
                        end

                        if((isDebuff and icons.showDebuffType) or (not isDebuff and icons.showBuffType) or icons.showType) then
                                local color = DebuffTypeColor[dtype] or DebuffTypeColor.none

                                icon.overlay:SetVertexColor(color.r, color.g, color.b)
                                icon.overlay:Show()
                        else
                                icon.overlay:Hide()
                        end

                        icon.icon:SetTexture(texture)
                        icon.count:SetText((count > 1 and count))

                        icon.filter = filter
                        icon.debuff = isDebuff

                        icon:SetID(index)
                        icon:Show()

                        if(self.PostUpdateAuraIcon) then
                                self:PostUpdateAuraIcon(icons, unit, icon, index, offset, filter, isDebuff)
                        end
                else
                        -- Hide the icon in-case we are in the middle of the stack.
                        icon:Hide()
                end

                return true
        end
end

local SetAuraPosition = function(self, icons, x)
        if(icons and x > 0) then
                local col = 0
                local row = 0
                local spacing = icons.spacing or 0
                local gap = icons.gap
                local size = (icons.size or 16) + spacing
                local anchor = icons.initialAnchor or "BOTTOMLEFT"
                local growthx = (icons["growth-x"] == "LEFT" and -1) or 1
                local growthy = (icons["growth-y"] == "DOWN" and -1) or 1
                local cols = math.floor(icons:GetWidth() / size + .5)
                local rows = math.floor(icons:GetHeight() / size + .5)

                for i = 1, #icons do
                        local button = icons[i]
                        if(button and button:IsShown()) then
                                if(gap and button.debuff) then
                                        if(col > 0) then
                                                col = col + 1
                                        end

                                        gap = false
                                end

                                if(col >= cols) then
                                        col = 0
                                        row = row + 1
                                end
                                button:ClearAllPoints()
                                button:SetPoint(anchor, icons, anchor, col * size * growthx, row * size * growthy)

                                col = col + 1
                        elseif(not button) then
                                break
                        end
                end
        end
end

local Update = function(self, event, unit)
        if(self.unit ~= unit) then return end
        if(self.PreUpdateAura) then self:PreUpdateAura(event, unit) end

        local auras, buffs, debuffs = self.Auras, self.Buffs, self.Debuffs

        if(auras) then
                local buffs = auras.numBuffs or 32
                local debuffs = auras.numDebuffs or 40
                local max = debuffs + buffs

                local visibleBuffs, visibleDebuffs = 0, 0
                for index = 1, max do
                        if(index > buffs) then
                                if(updateIcon(self, unit, auras, index % debuffs, visibleBuffs, auras.debuffFilter or auras.filter or 'HARMFUL', true, debuffs)) then
                                        visibleDebuffs = visibleDebuffs + 1
                                end
                        else
                                if(updateIcon(self, unit, auras, index, 0, auras.buffFilter or  auras.filter or 'HELPFUL')) then
                                        visibleBuffs = visibleBuffs + 1
                                end
                        end
                end

                local index = visibleBuffs + visibleDebuffs + 1
                while(auras[index]) do
                        auras[index]:Hide()
                        index = index + 1
                end

                auras.visibleBuffs = visibleBuffs
                auras.visibleDebuffs = visibleDebuffs
                auras.visibleAuras = visibleBuffs + visibleDebuffs

                if(self.PreAuraSetPosition) then self:PreAuraSetPosition(auras, max) end
                self:SetAuraPosition(auras, max)
        end

        if(buffs) then
                local filter = buffs.filter or 'HELPFUL'
                local max = buffs.num or 32
                local visibleBuffs = 0
                for index = 1, max do
                        if(not updateIcon(self, unit, buffs, index, 0, filter)) then
                                max = index - 1

                                while(buffs[index]) do
                                        buffs[index]:Hide()
                                        index = index + 1
                                end
                                break
                        end

                        visibleBuffs = visibleBuffs + 1
                end

                buffs.visibleBuffs = visibleBuffs

                if(self.PreAuraSetPosition) then self:PreAuraSetPosition(buffs, max) end
                self:SetAuraPosition(buffs, max)
        end

        if(debuffs) then
                local filter = debuffs.filter or 'HARMFUL'
                local max = debuffs.num or 40
                local visibleDebuffs = 0
                for index = 1, max do
                        if(not updateIcon(self, unit, debuffs, index, 0, filter, true)) then
                                max = index - 1

                                while(debuffs[index]) do
                                        debuffs[index]:Hide()
                                        index = index + 1
                                end
                                break
                        end

                        visibleDebuffs = visibleDebuffs + 1
                end
                debuffs.visibleDebuffs = visibleDebuffs

                if(self.PreAuraSetPosition) then self:PreAuraSetPosition(debuffs, max) end
                self:SetAuraPosition(debuffs, max)
        end

        if(self.PostUpdateAura) then
                return self:PostUpdateAura(event, unit)
        end
end

local Enable = function(self)
        if(self.Buffs or self.Debuffs or self.Auras) then
                if(not self.SetAuraPosition) then 
                        self.SetAuraPosition = SetAuraPosition
                end
                self:RegisterEvent("UNIT_AURA", Update)

                return true
        end
end

local Disable = function(self)
        if(self.Buffs or self.Debuffs or self.Auras) then
                self:UnregisterEvent("UNIT_AURA", Update)
        end
end

oUF:AddElement('Aura', Update, Enable, Disable)

Compare with Previous | Blame