ElvUI/Modules/UnitFrames/Elements/ClassBars.lua

514 lines
18 KiB
Lua
Raw Normal View History

2020-11-13 14:27:50 -05:00
local E, L, V, P, G = unpack(select(2, ...)); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
local UF = E:GetModule('UnitFrames');
local max = max
local unpack = unpack
local CreateFrame = CreateFrame
local UnitHasVehicleUI = UnitHasVehicleUI
local MAX_COMBO_POINTS = MAX_COMBO_POINTS
-- GLOBALS: ElvUF_Player
local _, ns = ...
local ElvUF = ns.oUF
assert(ElvUF, 'ElvUI was unable to locate oUF.')
function UF:PostVisibility_ClassBars(frame)
if not (frame and frame.db) then return end
UF:Configure_ClassBar(frame)
UF:Configure_Power(frame)
UF:Configure_InfoPanel(frame)
end
function UF:Configure_ClassBar(frame)
local db = frame.db
if not db then return end
local bars = frame[frame.ClassBar]
if not bars then return end
bars.Holder = frame.ClassBarHolder
bars.origParent = frame
--Fix height in case it is lower than the theme allows, or in case it's higher than 30px when not detached
if not UF.thinBorders and (frame.CLASSBAR_HEIGHT > 0 and frame.CLASSBAR_HEIGHT < 7) then --A height of 7 means 6px for borders and just 1px for the actual power statusbar
frame.CLASSBAR_HEIGHT = 7
if db.classbar then db.classbar.height = 7 end
elseif UF.thinBorders and (frame.CLASSBAR_HEIGHT > 0 and frame.CLASSBAR_HEIGHT < 3) then --A height of 3 means 2px for borders and just 1px for the actual power statusbar
frame.CLASSBAR_HEIGHT = 3
if db.classbar then db.classbar.height = 3 end
elseif not frame.CLASSBAR_DETACHED and frame.CLASSBAR_HEIGHT > 30 then
frame.CLASSBAR_HEIGHT = 10
if db.classbar then db.classbar.height = 10 end
end
-- keep after classbar height update
UF.ToggleResourceBar(bars)
--We don't want to modify the original frame.CLASSBAR_WIDTH value, as it bugs out when the classbar gains more buttons
local CLASSBAR_WIDTH = frame.CLASSBAR_WIDTH
local SPACING = (UF.BORDER + UF.SPACING)*2
local color = E.db.unitframe.colors.borderColor
if not bars.backdrop.forcedBorderColors then
bars.backdrop:SetBackdropBorderColor(color.r, color.g, color.b)
end
if frame.USE_MINI_CLASSBAR and not frame.CLASSBAR_DETACHED then
if frame.MAX_CLASS_BAR == 1 or frame.ClassBar == 'AdditionalPower' or frame.ClassBar == 'Stagger' or frame.ClassBar == 'AlternativePower' then
CLASSBAR_WIDTH = CLASSBAR_WIDTH * 2/3
else
CLASSBAR_WIDTH = CLASSBAR_WIDTH * (frame.MAX_CLASS_BAR - 1) / frame.MAX_CLASS_BAR
end
elseif frame.CLASSBAR_DETACHED then --Detached
CLASSBAR_WIDTH = db.classbar.detachedWidth
end
bars:Width(CLASSBAR_WIDTH - SPACING)
bars:Height(frame.CLASSBAR_HEIGHT - SPACING)
if frame.ClassBar == 'ClassPower' or frame.ClassBar == 'Runes' then
if E.myclass == 'DEATHKNIGHT' and frame.ClassBar == 'Runes' then
bars.sortOrder = (db.classbar.sortDirection ~= 'NONE') and db.classbar.sortDirection
end
local maxClassBarButtons = max(UF.classMaxResourceBar[E.myclass] or 0, MAX_COMBO_POINTS)
for i = 1, maxClassBarButtons do
bars[i].backdrop:Hide()
if i <= frame.MAX_CLASS_BAR then
if not bars[i].backdrop.forcedBorderColors then
bars[i].backdrop:SetBackdropBorderColor(color.r, color.g, color.b)
end
bars[i]:Height(bars:GetHeight())
if frame.MAX_CLASS_BAR == 1 then
bars[i]:Width(CLASSBAR_WIDTH)
elseif frame.USE_MINI_CLASSBAR then
if frame.CLASSBAR_DETACHED and db.classbar.orientation == 'VERTICAL' then
bars[i]:Width(CLASSBAR_WIDTH)
else
bars[i]:Width((CLASSBAR_WIDTH - ((5 + (UF.BORDER*2 + UF.SPACING*2))*(frame.MAX_CLASS_BAR - 1)))/frame.MAX_CLASS_BAR) --Width accounts for 5px spacing between each button, excluding borders
end
elseif i ~= frame.MAX_CLASS_BAR then
bars[i]:Width((CLASSBAR_WIDTH - ((frame.MAX_CLASS_BAR-1)*(UF.BORDER*2-UF.SPACING))) / frame.MAX_CLASS_BAR) --classbar width minus total width of dividers between each button, divided by number of buttons
end
bars[i]:GetStatusBarTexture():SetHorizTile(false)
bars[i]:ClearAllPoints()
if i == 1 then
bars[i]:Point('LEFT', bars)
else
if frame.USE_MINI_CLASSBAR then
if frame.CLASSBAR_DETACHED and db.classbar.orientation == 'VERTICAL' then
bars[i]:Point('BOTTOM', bars[i-1], 'TOP', 0, (db.classbar.spacing + UF.BORDER*2 + UF.SPACING*2))
else
bars[i]:Point('LEFT', bars[i-1], 'RIGHT', (db.classbar.spacing + UF.BORDER*2 + UF.SPACING*2), 0) --5px spacing between borders of each button(replaced with Detached Spacing option)
end
elseif i == frame.MAX_CLASS_BAR then
bars[i]:Point('LEFT', bars[i-1], 'RIGHT', UF.BORDER-UF.SPACING, 0)
bars[i]:Point('RIGHT', bars)
else
bars[i]:Point('LEFT', bars[i-1], 'RIGHT', UF.BORDER-UF.SPACING, 0)
end
end
if not frame.USE_MINI_CLASSBAR then
bars[i].backdrop:Hide()
else
bars[i].backdrop:Show()
end
if E.myclass == 'MONK' then
bars[i]:SetStatusBarColor(unpack(ElvUF.colors.ClassBars[E.myclass][i]))
elseif E.myclass == 'PALADIN' or E.myclass == 'MAGE' or E.myclass == 'WARLOCK' then
bars[i]:SetStatusBarColor(unpack(ElvUF.colors.ClassBars[E.myclass]))
elseif E.myclass == 'DEATHKNIGHT' and frame.ClassBar == 'Runes' then
local r, g, b = unpack(ElvUF.colors.ClassBars.DEATHKNIGHT)
bars[i]:SetStatusBarColor(r, g, b)
if bars[i].bg then
local mu = bars[i].bg.multiplier or 1
bars[i].bg:SetVertexColor(r * mu, g * mu, b * mu)
end
else -- Combo Points for everyone else
local r1, g1, b1 = unpack(ElvUF.colors.ComboPoints[1])
local r2, g2, b2 = unpack(ElvUF.colors.ComboPoints[2])
local r3, g3, b3 = unpack(ElvUF.colors.ComboPoints[3])
local maxComboPoints = ((frame.MAX_CLASS_BAR == 10 and 10) or (frame.MAX_CLASS_BAR > 5 and 6 or 5))
bars[i]:SetStatusBarColor(ElvUF:ColorGradient(i, maxComboPoints, r1, g1, b1, r2, g2, b2, r3, g3, b3))
end
if frame.CLASSBAR_DETACHED and db.classbar.verticalOrientation then
bars[i]:SetOrientation('VERTICAL')
else
bars[i]:SetOrientation('HORIZONTAL')
end
--Fix missing backdrop colors on Combo Points when using Spaced style
if frame.ClassBar == 'ClassPower' then
if frame.USE_MINI_CLASSBAR then
bars[i].bg:SetParent(bars[i].backdrop)
else
bars[i].bg:SetParent(bars)
end
end
end
end
if (not frame.USE_MINI_CLASSBAR) and frame.USE_CLASSBAR then
bars.backdrop:Show()
else
bars.backdrop:Hide()
end
elseif frame.ClassBar == 'AdditionalPower' or frame.ClassBar == 'Stagger' or frame.ClassBar == 'AlternativePower' then
if frame.CLASSBAR_DETACHED and db.classbar.verticalOrientation then
bars:SetOrientation('VERTICAL')
else
bars:SetOrientation('HORIZONTAL')
end
end
if frame.USE_MINI_CLASSBAR and not frame.CLASSBAR_DETACHED then
bars:ClearAllPoints()
bars:Point('CENTER', frame.Health.backdrop, 'TOP', 0, 0)
bars:SetFrameLevel(50) --RaisedElementParent uses 100, we want it lower than this
if bars.Holder and bars.Holder.mover then
E:DisableMover(bars.Holder.mover:GetName())
end
elseif frame.CLASSBAR_DETACHED then
bars.Holder:Size(db.classbar.detachedWidth, db.classbar.height)
bars:ClearAllPoints()
bars:Point('BOTTOMLEFT', bars.Holder, 'BOTTOMLEFT', UF.BORDER + UF.SPACING, UF.BORDER + UF.SPACING)
if not bars.Holder.mover then
E:CreateMover(bars.Holder, 'ClassBarMover', L["Classbar"], nil, nil, nil, 'ALL,SOLO', nil, 'unitframe,individualUnits,player,classbar')
else
E:EnableMover(bars.Holder.mover:GetName())
end
if not db.classbar.strataAndLevel.useCustomStrata then
bars:SetFrameStrata('LOW')
else
bars:SetFrameStrata(db.classbar.strataAndLevel.frameStrata)
end
if not db.classbar.strataAndLevel.useCustomLevel then
bars:SetFrameLevel(frame.Health:GetFrameLevel() + 10) --Health uses 10, Power uses (Health + 5) when attached
else
bars:SetFrameLevel(db.classbar.strataAndLevel.frameLevel)
end
else
bars:ClearAllPoints()
if frame.ORIENTATION == 'RIGHT' then
bars:Point('BOTTOMRIGHT', frame.Health.backdrop, 'TOPRIGHT', -UF.BORDER, UF.SPACING*3)
else
bars:Point('BOTTOMLEFT', frame.Health.backdrop, 'TOPLEFT', UF.BORDER, UF.SPACING*3)
end
bars:SetFrameStrata('LOW')
bars:SetFrameLevel(frame.Health:GetFrameLevel() + 10) --Health uses 10, Power uses (Health + 5) when attached
if bars.Holder and bars.Holder.mover then
E:DisableMover(bars.Holder.mover:GetName())
end
end
if frame.CLASSBAR_DETACHED and db.classbar.parent == 'UIPARENT' then
E.FrameLocks[bars] = true
bars:SetParent(E.UIParent)
else
E.FrameLocks[bars] = nil
bars:SetParent(frame)
end
if frame.USE_CLASSBAR then
if frame.ClassPower and not frame:IsElementEnabled('ClassPower') then
frame:EnableElement('ClassPower')
end
if frame.AdditionalPower and not frame:IsElementEnabled('AdditionalPower') then
frame:EnableElement('AdditionalPower')
end
if frame.Runes and not frame:IsElementEnabled('Runes') then
frame:EnableElement('Runes')
end
if frame.Stagger and not frame:IsElementEnabled('Stagger') then
frame:EnableElement('Stagger')
end
if frame.AlternativePower and not frame:IsElementEnabled('AlternativePower') then
frame:EnableElement('AlternativePower')
end
else
if frame.ClassPower and frame:IsElementEnabled('ClassPower') then
frame:DisableElement('ClassPower')
end
if frame.AdditionalPower and frame:IsElementEnabled('AdditionalPower') then
frame:DisableElement('AdditionalPower')
end
if frame.Runes and frame:IsElementEnabled('Runes') then
frame:DisableElement('Runes')
end
if frame.Stagger and frame:IsElementEnabled('Stagger') then
frame:DisableElement('Stagger')
end
if frame.AlternativePower and frame:IsElementEnabled('AlternativePower') then
frame:DisableElement('AlternativePower')
end
end
end
local function ToggleResourceBar(bars)
local frame = bars.origParent or bars:GetParent()
local db = frame.db
if not db then return end
frame.CLASSBAR_SHOWN = frame[frame.ClassBar]:IsShown()
if bars.text then bars.text:SetAlpha(frame.CLASSBAR_SHOWN and 1 or 0) end
frame.CLASSBAR_HEIGHT = frame.USE_CLASSBAR and ((db.classbar and db.classbar.height) or (frame.AlternativePower and db.power.height)) or 0
frame.CLASSBAR_YOFFSET = (not frame.USE_CLASSBAR or not frame.CLASSBAR_SHOWN or frame.CLASSBAR_DETACHED) and 0 or (frame.USE_MINI_CLASSBAR and ((UF.SPACING+(frame.CLASSBAR_HEIGHT/2))) or (frame.CLASSBAR_HEIGHT - (UF.BORDER-UF.SPACING)))
UF:Configure_CustomTexts(frame)
UF:Configure_HealthBar(frame)
UF:Configure_Portrait(frame)
-- keep this after the configure_healtbar, we need the one updated before we match the healpred size to -1
if frame.HealthPrediction then
UF:SetSize_HealComm(frame)
end
end
UF.ToggleResourceBar = ToggleResourceBar --Make available to combobar
-------------------------------------------------------------
-- MONK, PALADIN, WARLOCK, MAGE, and COMBOS
-------------------------------------------------------------
function UF:Construct_ClassBar(frame)
local bars = CreateFrame('Frame', '$parent_ClassBar', frame, 'BackdropTemplate')
bars:CreateBackdrop(nil, nil, nil, nil, true)
bars:Hide()
local maxBars = max(UF.classMaxResourceBar[E.myclass] or 0, MAX_COMBO_POINTS)
for i = 1, maxBars do
bars[i] = CreateFrame('StatusBar', frame:GetName()..'ClassIconButton'..i, bars)
bars[i]:SetStatusBarTexture(E.media.blankTex) --Dummy really, this needs to be set so we can change the color
bars[i]:GetStatusBarTexture():SetHorizTile(false)
UF.statusbars[bars[i]] = true
bars[i]:CreateBackdrop(nil, nil, nil, nil, true)
bars[i].backdrop:SetParent(bars)
bars[i].bg = bars:CreateTexture(nil, 'BORDER')
bars[i].bg:SetAllPoints(bars[i])
bars[i].bg:SetTexture(E.media.blankTex)
end
bars.PostVisibility = UF.PostVisibilityClassBar
bars.PostUpdate = UF.UpdateClassBar
bars.UpdateColor = E.noop --We handle colors on our own in Configure_ClassBar
bars.UpdateTexture = E.noop --We don't use textures but statusbars, so prevent errors
bars:SetScript('OnShow', ToggleResourceBar)
bars:SetScript('OnHide', ToggleResourceBar)
return bars
end
function UF:PostVisibilityClassBar()
UF:PostVisibility_ClassBars(self.origParent or self:GetParent())
end
function UF:UpdateClassBar(current, maxBars, hasMaxChanged)
local frame = self.origParent or self:GetParent()
local db = frame.db
if not db then return end
local isShown = self:IsShown()
local stateChanged
if not frame.USE_CLASSBAR or (current == 0 and db.classbar.autoHide) or maxBars == nil then
self:Hide()
if isShown then
stateChanged = true
end
else
self:Show()
if not isShown then
stateChanged = true
end
end
if hasMaxChanged then
frame.MAX_CLASS_BAR = maxBars
UF:Configure_ClassBar(frame, current)
elseif stateChanged then
UF:Configure_ClassBar(frame, current)
end
local custom_backdrop = UF.db.colors.customclasspowerbackdrop and UF.db.colors.classpower_backdrop
for i=1, #self do
if custom_backdrop then
self[i].bg:SetVertexColor(custom_backdrop.r, custom_backdrop.g, custom_backdrop.b)
else
local r, g, b = self[i]:GetStatusBarColor()
self[i].bg:SetVertexColor(r * .35, g * .35, b * .35)
end
if maxBars and (i <= maxBars) then
self[i].bg:Show()
else
self[i].bg:Hide()
end
end
end
-------------------------------------------------------------
-- DEATHKNIGHT
-------------------------------------------------------------
local function PostUpdateRunes(self)
local useRunes = not UnitHasVehicleUI('player')
if useRunes then
self:Show()
else
self:Hide()
end
local custom_backdrop = UF.db.colors.customclasspowerbackdrop and UF.db.colors.classpower_backdrop
for i=1, #self do
if custom_backdrop then
self[i].bg:SetVertexColor(custom_backdrop.r, custom_backdrop.g, custom_backdrop.b)
else
local r, g, b = self[i]:GetStatusBarColor()
self[i].bg:SetVertexColor(r * .35, g * .35, b * .35)
end
end
end
function UF:Construct_DeathKnightResourceBar(frame)
local runes = CreateFrame('Frame', '$parent_Runes', frame)
runes:CreateBackdrop(nil, nil, nil, nil, true)
runes.backdrop:Hide()
for i = 1, UF.classMaxResourceBar[E.myclass] do
runes[i] = CreateFrame('StatusBar', frame:GetName()..'RuneButton'..i, runes)
runes[i]:SetStatusBarTexture(E.media.blankTex)
runes[i]:GetStatusBarTexture():SetHorizTile(false)
UF.statusbars[runes[i]] = true
runes[i]:CreateBackdrop(nil, nil, nil, nil, true)
runes[i].backdrop:SetParent(runes)
runes[i].bg = runes[i]:CreateTexture(nil, 'BORDER')
runes[i].bg:SetAllPoints()
runes[i].bg:SetTexture(E.media.blankTex)
runes[i].bg.multiplier = 0.35
end
runes.PostUpdate = PostUpdateRunes
runes.UpdateColor = E.noop --We handle colors on our own in Configure_ClassBar
runes:SetScript('OnShow', ToggleResourceBar)
runes:SetScript('OnHide', ToggleResourceBar)
return runes
end
-------------------------------------------------------------
-- ALTERNATIVE MANA BAR
-------------------------------------------------------------
function UF:Construct_AdditionalPowerBar(frame)
local additionalPower = CreateFrame('StatusBar', '$parent_AdditionalPowerBar', frame)
additionalPower.colorPower = true
additionalPower.frequentUpdates = true
additionalPower.PostUpdate = UF.PostUpdateAdditionalPower
additionalPower.PostUpdateColor = UF.PostColorAdditionalPower
additionalPower.PostVisibility = UF.PostVisibilityAdditionalPower
additionalPower:CreateBackdrop(nil, nil, nil, nil, true)
additionalPower:SetStatusBarTexture(E.media.blankTex)
UF.statusbars[additionalPower] = true
additionalPower.RaisedElementParent = CreateFrame('Frame', nil, additionalPower)
additionalPower.RaisedElementParent:SetFrameLevel(additionalPower:GetFrameLevel() + 100)
additionalPower.RaisedElementParent:SetAllPoints()
additionalPower.text = additionalPower.RaisedElementParent:CreateFontString(nil, 'OVERLAY')
UF:Configure_FontString(additionalPower.text)
additionalPower.bg = additionalPower:CreateTexture(nil, 'BORDER')
additionalPower.bg:SetAllPoints(additionalPower)
additionalPower.bg:SetTexture(E.media.blankTex)
additionalPower.bg.multiplier = 0.35
additionalPower:SetScript('OnShow', ToggleResourceBar)
additionalPower:SetScript('OnHide', ToggleResourceBar)
return additionalPower
end
function UF:PostColorAdditionalPower()
local frame = self.origParent or self:GetParent()
if frame.USE_CLASSBAR then
local custom_backdrop = UF.db.colors.customclasspowerbackdrop and UF.db.colors.classpower_backdrop
if custom_backdrop then
self.bg:SetVertexColor(custom_backdrop.r, custom_backdrop.g, custom_backdrop.b)
end
end
end
function UF:PostUpdateAdditionalPower(CUR, MAX, event)
local frame = self.origParent or self:GetParent()
local db = frame.db
if frame.USE_CLASSBAR and event ~= 'ElementDisable' and (CUR ~= MAX or not db.classbar.autoHide) then
self:Show()
else
self:Hide()
end
end
function UF:PostVisibilityAdditionalPower(enabled)
local frame = self.origParent or self:GetParent()
frame.ClassBar = (enabled and 'AdditionalPower') or 'ClassPower'
UF:PostVisibility_ClassBars(frame)
end
-----------------------------------------------------------
-- Stagger Bar
-----------------------------------------------------------
function UF:Construct_Stagger(frame)
local stagger = CreateFrame('Statusbar', '$parent_Stagger', frame)
stagger:CreateBackdrop(nil,nil, nil, nil, true)
stagger.PostUpdate = UF.PostUpdateStagger
stagger.PostVisibility = UF.PostUpdateVisibilityStagger
UF.statusbars[stagger] = true
stagger:SetScript('OnShow', ToggleResourceBar)
stagger:SetScript('OnHide', ToggleResourceBar)
return stagger
end
function UF:PostUpdateStagger(stagger)
local frame = self.origParent or self:GetParent()
local db = frame.db
if not frame.USE_CLASSBAR or (stagger == 0 and db.classbar.autoHide) then
self:Hide()
else
self:Show()
end
end
function UF:PostUpdateVisibilityStagger(_, _, isShown, stateChanged)
self.ClassBar = (isShown and 'Stagger') or 'ClassPower'
if stateChanged then
UF:PostVisibility_ClassBars(self)
end
end