458 lines
14 KiB
Lua
458 lines
14 KiB
Lua
|
local E, L, V, P, G = unpack(select(2, ...)) --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
|
||
|
local UF = E:GetModule('UnitFrames')
|
||
|
local LSM = E.Libs.LSM
|
||
|
|
||
|
local _G = _G
|
||
|
local pairs = pairs
|
||
|
local select = select
|
||
|
local assert = assert
|
||
|
local tinsert = tinsert
|
||
|
local strsub = strsub
|
||
|
local CreateFrame = CreateFrame
|
||
|
local UnitClass = UnitClass
|
||
|
local UnitExists = UnitExists
|
||
|
local UnitIsPlayer = UnitIsPlayer
|
||
|
local UnitIsUnit = UnitIsUnit
|
||
|
local UnitReaction = UnitReaction
|
||
|
|
||
|
function UF:FrameGlow_MouseOnUnit(frame)
|
||
|
if frame and frame:IsVisible() and UnitExists('mouseover') then
|
||
|
local unit = frame.unit or (frame.isForced and 'player')
|
||
|
return unit and UnitIsUnit('mouseover', unit)
|
||
|
end
|
||
|
|
||
|
return false
|
||
|
end
|
||
|
|
||
|
function UF:FrameGlow_ElementHook(frame, glow, which)
|
||
|
if not (frame and frame.__elements) then return end
|
||
|
tinsert(frame.__elements, function()
|
||
|
local unit = frame.unit or (frame.isForced and 'player')
|
||
|
if unit then
|
||
|
UF:FrameGlow_SetGlowColor(glow, unit, which)
|
||
|
end
|
||
|
|
||
|
if which == 'mouseoverGlow' then
|
||
|
UF:FrameGlow_PositionTexture(frame)
|
||
|
UF:FrameGlow_CheckMouseover(frame)
|
||
|
else
|
||
|
UF:FrameGlow_PositionGlow(frame, glow, glow.powerGlow)
|
||
|
end
|
||
|
|
||
|
if which == 'targetGlow' then
|
||
|
UF:FrameGlow_CheckTarget(frame)
|
||
|
end
|
||
|
|
||
|
if which == 'focusGlow' then
|
||
|
UF:FrameGlow_CheckFocus(frame)
|
||
|
end
|
||
|
end)
|
||
|
end
|
||
|
|
||
|
function UF:FrameGlow_HookPowerBar(frame, power, powerName, glow, offset)
|
||
|
if (frame and power and powerName and glow and offset) and not glow[powerName..'Hooked'] then
|
||
|
glow[powerName..'Hooked'] = true
|
||
|
local func = function() UF:FrameGlow_ClassGlowPosition(frame, powerName, glow, offset, true) end
|
||
|
power:HookScript('OnShow', func)
|
||
|
power:HookScript('OnHide', func)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
function UF:FrameGlow_ClassGlowPosition(frame, powerName, glow, offset, fromScript)
|
||
|
if not (frame and glow and offset) then return end
|
||
|
|
||
|
local power = powerName and frame[powerName]
|
||
|
if not power then return end
|
||
|
|
||
|
-- check for Additional Power to hook scripts on
|
||
|
local useBonusPower, bonus
|
||
|
if powerName == 'ClassPower' then
|
||
|
local bonusName = (frame.AdditionalPower and 'AdditionalPower') or (frame.Stagger and 'Stagger') or (frame.Runes and 'Runes')
|
||
|
bonus = bonusName and frame[bonusName]
|
||
|
|
||
|
if bonus then
|
||
|
if not fromScript then
|
||
|
UF:FrameGlow_HookPowerBar(frame, bonus, bonusName, glow, offset)
|
||
|
end
|
||
|
|
||
|
useBonusPower = bonus:IsVisible()
|
||
|
end
|
||
|
end
|
||
|
|
||
|
if not fromScript then
|
||
|
UF:FrameGlow_HookPowerBar(frame, power, powerName, glow, offset)
|
||
|
end
|
||
|
|
||
|
if useBonusPower then
|
||
|
power = bonus
|
||
|
end
|
||
|
|
||
|
local portrait = (frame.USE_PORTRAIT and not frame.USE_PORTRAIT_OVERLAY) and (frame.Portrait and frame.Portrait.backdrop)
|
||
|
if (power and power.backdrop and power:IsVisible()) and ((power == frame.AlternativePower and not frame.USE_MINI_CLASSBAR) or not (frame.CLASSBAR_DETACHED or frame.USE_MINI_CLASSBAR)) then
|
||
|
glow:SetPoint('TOPLEFT', (frame.ORIENTATION == 'LEFT' and portrait) or power.backdrop, -offset, offset)
|
||
|
glow:SetPoint('TOPRIGHT', (frame.ORIENTATION == 'RIGHT' and portrait) or power.backdrop, offset, offset)
|
||
|
elseif frame.Health and frame.Health.backdrop then
|
||
|
glow:SetPoint('TOPLEFT', (frame.ORIENTATION == 'LEFT' and portrait) or frame.Health.backdrop, -offset, offset)
|
||
|
glow:SetPoint('TOPRIGHT', (frame.ORIENTATION == 'RIGHT' and portrait) or frame.Health.backdrop, offset, offset)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
function UF:FrameGlow_PositionGlow(frame, mainGlow, powerGlow)
|
||
|
if not frame then return end
|
||
|
|
||
|
local infoPanel = frame.InfoPanel
|
||
|
local classPower = frame.ClassPower
|
||
|
local altPower = frame.AlternativePower
|
||
|
local pvpSpec = frame.PVPSpecIcon
|
||
|
local power = frame.Power and frame.Power.backdrop
|
||
|
local health = frame.Health and frame.Health.backdrop
|
||
|
local portrait = (frame.USE_PORTRAIT and not frame.USE_PORTRAIT_OVERLAY) and (frame.Portrait and frame.Portrait.backdrop)
|
||
|
local offset = (UF.thinBorders and 4) or 5 -- edgeSize is 3
|
||
|
|
||
|
mainGlow:ClearAllPoints()
|
||
|
mainGlow:SetPoint('TOPLEFT', (frame.ORIENTATION == 'LEFT' and portrait) or health, -offset, offset)
|
||
|
mainGlow:SetPoint('TOPRIGHT', (frame.ORIENTATION == 'RIGHT' and portrait) or health, offset, offset)
|
||
|
|
||
|
if frame.USE_POWERBAR_OFFSET or frame.USE_MINI_POWERBAR then
|
||
|
mainGlow:SetPoint('BOTTOMLEFT', health, -offset, -offset)
|
||
|
mainGlow:SetPoint('BOTTOMRIGHT', health, offset, -offset)
|
||
|
else
|
||
|
--offset is set because its one pixel off for some reason
|
||
|
mainGlow:SetPoint('BOTTOMLEFT', frame, -offset, -(UF.thinBorders and offset or offset-1))
|
||
|
mainGlow:SetPoint('BOTTOMRIGHT', frame, offset, -(UF.thinBorders and offset or offset-1))
|
||
|
end
|
||
|
|
||
|
if powerGlow then
|
||
|
powerGlow:ClearAllPoints()
|
||
|
powerGlow:SetPoint('TOPLEFT', power, -offset, offset)
|
||
|
powerGlow:SetPoint('TOPRIGHT', power, offset, offset)
|
||
|
powerGlow:SetPoint('BOTTOMLEFT', power, -offset, -offset)
|
||
|
powerGlow:SetPoint('BOTTOMRIGHT', power, offset, -offset)
|
||
|
end
|
||
|
|
||
|
if classPower then
|
||
|
UF:FrameGlow_ClassGlowPosition(frame, 'ClassPower', mainGlow, offset)
|
||
|
elseif altPower then
|
||
|
UF:FrameGlow_ClassGlowPosition(frame, 'AlternativePower', mainGlow, offset)
|
||
|
elseif pvpSpec and pvpSpec:IsShown() then
|
||
|
local shownPanel = (infoPanel and infoPanel:IsShown() and infoPanel.backdrop)
|
||
|
mainGlow:SetPoint('TOPLEFT', pvpSpec.bg, -offset, offset)
|
||
|
mainGlow:SetPoint('BOTTOMLEFT', shownPanel or pvpSpec.bg, -offset, -offset)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
function UF:FrameGlow_CreateGlow(frame, which)
|
||
|
-- Main Glow to wrap the health frame to it's best ability
|
||
|
local mainGlow = frame:CreateShadow(4, true)
|
||
|
mainGlow:SetFrameStrata('BACKGROUND')
|
||
|
mainGlow:Hide()
|
||
|
|
||
|
-- Secondary Glow for power frame when using power offset or mini power
|
||
|
local powerGlow = frame:CreateShadow(4, true)
|
||
|
powerGlow:SetFrameStrata('BACKGROUND')
|
||
|
powerGlow:Hide()
|
||
|
|
||
|
local level = (which == 'mouse' and 5) or (which == 'target' and 4) or 3
|
||
|
mainGlow:SetFrameLevel(level)
|
||
|
powerGlow:SetFrameLevel(level)
|
||
|
|
||
|
-- Eventing Frame
|
||
|
if not frame.FrameGlow then
|
||
|
frame.FrameGlow = CreateFrame('Frame', nil, frame)
|
||
|
frame.FrameGlow:Hide()
|
||
|
frame.FrameGlow:SetScript('OnEvent', function(_, event)
|
||
|
if event == 'UPDATE_MOUSEOVER_UNIT' then
|
||
|
UF:FrameGlow_CheckMouseover(frame)
|
||
|
elseif event == 'PLAYER_FOCUS_CHANGED' then
|
||
|
UF:FrameGlow_CheckFocus(frame)
|
||
|
elseif event == 'PLAYER_TARGET_CHANGED' then
|
||
|
UF:FrameGlow_CheckTarget(frame)
|
||
|
end
|
||
|
end)
|
||
|
end
|
||
|
|
||
|
mainGlow.powerGlow = powerGlow
|
||
|
return mainGlow
|
||
|
end
|
||
|
|
||
|
function UF:FrameGlow_SetGlowColor(glow, unit, which)
|
||
|
if not glow then return end
|
||
|
local option = E.db.unitframe.colors.frameGlow[which]
|
||
|
local r, g, b, a = 1, 1, 1, 1
|
||
|
|
||
|
if option.color then
|
||
|
local color = option.color
|
||
|
r, g, b, a = color.r, color.g, color.b, color.a
|
||
|
end
|
||
|
|
||
|
if option.class then
|
||
|
local isPlayer = unit and UnitIsPlayer(unit)
|
||
|
local reaction = unit and UnitReaction(unit, 'player')
|
||
|
|
||
|
if isPlayer then
|
||
|
local _, class = UnitClass(unit)
|
||
|
if class then
|
||
|
local color = E:ClassColor(class)
|
||
|
if color then
|
||
|
r, g, b = color.r, color.g, color.b
|
||
|
end
|
||
|
end
|
||
|
elseif reaction then
|
||
|
local color = _G.FACTION_BAR_COLORS[reaction]
|
||
|
if color then
|
||
|
r, g, b = color.r, color.g, color.b
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
if which == 'mouseoverGlow' then
|
||
|
glow:SetVertexColor(r, g, b, a)
|
||
|
else
|
||
|
glow:SetBackdropBorderColor(r, g, b, a)
|
||
|
if glow.powerGlow then
|
||
|
glow.powerGlow:SetBackdropBorderColor(r, g, b, a)
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
function UF:FrameGlow_HideGlow(glow)
|
||
|
if not glow then return end
|
||
|
if glow:IsShown() then glow:Hide() end
|
||
|
if glow.powerGlow and glow.powerGlow:IsShown() then
|
||
|
glow.powerGlow:Hide()
|
||
|
end
|
||
|
end
|
||
|
|
||
|
function UF:FrameGlow_ConfigureGlow(frame, unit, dbTexture)
|
||
|
if not frame then return end
|
||
|
|
||
|
if not unit then
|
||
|
unit = frame.unit or (frame.isForced and 'player')
|
||
|
end
|
||
|
|
||
|
local shouldHide
|
||
|
if frame.FrameGlow and frame.FrameGlow.texture then
|
||
|
if E.db.unitframe.colors.frameGlow.mouseoverGlow.enable and not (frame.db and frame.db.disableMouseoverGlow) then
|
||
|
frame.FrameGlow.texture:SetTexture(dbTexture)
|
||
|
UF:FrameGlow_SetGlowColor(frame.FrameGlow.texture, unit, 'mouseoverGlow')
|
||
|
else
|
||
|
shouldHide = 'texture'
|
||
|
end
|
||
|
end
|
||
|
|
||
|
if frame.MouseGlow then
|
||
|
if E.db.unitframe.colors.frameGlow.mainGlow.enable and not (frame.db and frame.db.disableMouseoverGlow) then
|
||
|
UF:FrameGlow_SetGlowColor(frame.MouseGlow, unit, 'mainGlow')
|
||
|
else
|
||
|
UF:FrameGlow_HideGlow(frame.MouseGlow)
|
||
|
if shouldHide then
|
||
|
shouldHide = 'both'
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
if shouldHide then
|
||
|
if shouldHide == 'both' and frame.FrameGlow:IsShown() then
|
||
|
frame.FrameGlow:Hide()
|
||
|
elseif shouldHide == 'texture' then
|
||
|
frame.FrameGlow.texture:Hide()
|
||
|
end
|
||
|
end
|
||
|
|
||
|
if frame.TargetGlow then
|
||
|
UF:FrameGlow_CheckTarget(frame, true)
|
||
|
end
|
||
|
|
||
|
if frame.FocusGlow then
|
||
|
UF:FrameGlow_CheckFocus(frame, true)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
function UF:FrameGlow_CheckUnit(frame, element, setting, color, glowEnabled, frameDisabled)
|
||
|
if not (element and frame:IsVisible()) then return end
|
||
|
|
||
|
local unit = frame.unit or (frame.isForced and 'player')
|
||
|
if (glowEnabled and not frameDisabled) and unit and UnitIsUnit(unit, strsub(setting, 0, -5)) then
|
||
|
if color then
|
||
|
UF:FrameGlow_SetGlowColor(element, unit, setting)
|
||
|
end
|
||
|
if element.powerGlow then
|
||
|
if frame.USE_POWERBAR_OFFSET or frame.USE_MINI_POWERBAR then
|
||
|
element.powerGlow:Show()
|
||
|
elseif element.powerGlow:IsShown() then
|
||
|
element.powerGlow:Hide()
|
||
|
end
|
||
|
end
|
||
|
element:Show()
|
||
|
else
|
||
|
UF:FrameGlow_HideGlow(element)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
function UF:FrameGlow_CheckTarget(frame, color)
|
||
|
UF:FrameGlow_CheckUnit(frame, frame.TargetGlow, 'targetGlow', color, E.db.unitframe.colors.frameGlow.targetGlow.enable, frame.db and frame.db.disableTargetGlow)
|
||
|
end
|
||
|
|
||
|
function UF:FrameGlow_CheckFocus(frame, color)
|
||
|
UF:FrameGlow_CheckUnit(frame, frame.FocusGlow, 'focusGlow', color, E.db.unitframe.colors.frameGlow.focusGlow.enable, frame.db and frame.db.disableFocusGlow)
|
||
|
end
|
||
|
|
||
|
function UF:FrameGlow_CheckMouseover(frame)
|
||
|
if not (frame and frame.MouseGlow and frame:IsVisible()) then return end
|
||
|
|
||
|
local shouldShow
|
||
|
if UF:FrameGlow_MouseOnUnit(frame) then
|
||
|
if E.db.unitframe.colors.frameGlow.mainGlow.enable and not (frame.db and frame.db.disableMouseoverGlow) then
|
||
|
shouldShow = 'frame'
|
||
|
end
|
||
|
if E.db.unitframe.colors.frameGlow.mouseoverGlow.enable and not (frame.db and frame.db.disableMouseoverGlow) then
|
||
|
shouldShow = (shouldShow and 'both') or 'texture'
|
||
|
end
|
||
|
end
|
||
|
|
||
|
if shouldShow then
|
||
|
if frame.FrameGlow and not frame.FrameGlow:IsShown() then
|
||
|
frame.FrameGlow:Show()
|
||
|
end
|
||
|
if shouldShow == 'both' or shouldShow == 'frame' then
|
||
|
if frame.MouseGlow.powerGlow then
|
||
|
if frame.USE_POWERBAR_OFFSET or frame.USE_MINI_POWERBAR then
|
||
|
frame.MouseGlow.powerGlow:Show()
|
||
|
elseif frame.MouseGlow.powerGlow:IsShown() then
|
||
|
frame.MouseGlow.powerGlow:Hide()
|
||
|
end
|
||
|
end
|
||
|
frame.MouseGlow:Show()
|
||
|
|
||
|
if shouldShow == 'frame' and frame.FrameGlow.texture and frame.FrameGlow.texture:IsShown() then
|
||
|
frame.FrameGlow.texture:Hide()
|
||
|
end
|
||
|
end
|
||
|
if (shouldShow == 'both' or shouldShow == 'texture') and frame.FrameGlow.texture and not frame.FrameGlow.texture:IsShown() then
|
||
|
frame.FrameGlow.texture:Show()
|
||
|
end
|
||
|
elseif frame.FrameGlow and frame.FrameGlow:IsShown() then
|
||
|
frame.FrameGlow:Hide()
|
||
|
end
|
||
|
end
|
||
|
|
||
|
function UF:FrameGlow_PositionTexture(frame)
|
||
|
if frame.FrameGlow and frame.FrameGlow.texture then
|
||
|
frame.FrameGlow.texture:ClearAllPoints()
|
||
|
frame.FrameGlow.texture:SetPoint('TOPLEFT', frame.Health, 'TOPLEFT')
|
||
|
frame.FrameGlow.texture:SetPoint('BOTTOMRIGHT', frame.Health:GetStatusBarTexture(), 'BOTTOMRIGHT')
|
||
|
end
|
||
|
end
|
||
|
|
||
|
function UF:Configure_FrameGlow(frame)
|
||
|
if frame.FrameGlow and frame.FrameGlow.texture then
|
||
|
local dbTexture = LSM:Fetch('statusbar', E.db.unitframe.colors.frameGlow.mouseoverGlow.texture)
|
||
|
frame.FrameGlow.texture:SetTexture(dbTexture)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
function UF:Construct_FrameGlow(frame, glow)
|
||
|
if frame.Health and frame.FrameGlow then
|
||
|
frame.FrameGlow:SetScript('OnHide', function(watcher)
|
||
|
UF:FrameGlow_HideGlow(glow)
|
||
|
|
||
|
if watcher.texture and watcher.texture:IsShown() then
|
||
|
watcher.texture:Hide()
|
||
|
end
|
||
|
end)
|
||
|
|
||
|
frame.FrameGlow:SetScript('OnUpdate', function(watcher, elapsed)
|
||
|
if watcher.elapsed and watcher.elapsed > 0.1 then
|
||
|
if not UF:FrameGlow_MouseOnUnit(frame) then
|
||
|
watcher:Hide()
|
||
|
end
|
||
|
watcher.elapsed = 0
|
||
|
else
|
||
|
watcher.elapsed = (watcher.elapsed or 0) + elapsed
|
||
|
end
|
||
|
end)
|
||
|
|
||
|
frame.FrameGlow.texture = frame.Health:CreateTexture('$parentFrameGlow', 'ARTWORK', nil, 1)
|
||
|
frame.FrameGlow.texture:Hide()
|
||
|
|
||
|
UF:FrameGlow_ElementHook(frame, frame.FrameGlow.texture, 'mouseoverGlow')
|
||
|
end
|
||
|
end
|
||
|
|
||
|
function UF:Construct_MouseGlow(frame)
|
||
|
local mainGlow = UF:FrameGlow_CreateGlow(frame, 'mouse')
|
||
|
UF:FrameGlow_ElementHook(frame, mainGlow, 'mainGlow')
|
||
|
UF:Construct_FrameGlow(frame, mainGlow)
|
||
|
frame.FrameGlow:RegisterEvent('UPDATE_MOUSEOVER_UNIT')
|
||
|
|
||
|
return mainGlow
|
||
|
end
|
||
|
|
||
|
function UF:Construct_TargetGlow(frame)
|
||
|
local targetGlow = UF:FrameGlow_CreateGlow(frame, 'target')
|
||
|
UF:FrameGlow_ElementHook(frame, targetGlow, 'targetGlow')
|
||
|
frame.FrameGlow:RegisterEvent('PLAYER_TARGET_CHANGED')
|
||
|
|
||
|
return targetGlow
|
||
|
end
|
||
|
|
||
|
function UF:Construct_FocusGlow(frame)
|
||
|
local focusGlow = UF:FrameGlow_CreateGlow(frame, 'focus')
|
||
|
UF:FrameGlow_ElementHook(frame, focusGlow, 'focusGlow')
|
||
|
frame.FrameGlow:RegisterEvent('PLAYER_FOCUS_CHANGED')
|
||
|
|
||
|
return focusGlow
|
||
|
end
|
||
|
|
||
|
function UF:FrameGlow_CheckChildren(frame, dbTexture)
|
||
|
if frame.GetName then
|
||
|
local pet = _G[frame:GetName()..'Pet']
|
||
|
if pet then
|
||
|
UF:FrameGlow_ConfigureGlow(pet, pet.unit, dbTexture)
|
||
|
end
|
||
|
|
||
|
local target = _G[frame:GetName()..'Target']
|
||
|
if target then
|
||
|
UF:FrameGlow_ConfigureGlow(target, target.unit, dbTexture)
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
function UF:FrameGlow_UpdateFrames()
|
||
|
local dbTexture = LSM:Fetch('statusbar', E.db.unitframe.colors.frameGlow.mouseoverGlow.texture)
|
||
|
|
||
|
-- focus, focustarget, pet, pettarget, player, target, targettarget, targettargettarget
|
||
|
for unit in pairs(self.units) do
|
||
|
UF:FrameGlow_ConfigureGlow(self[unit], unit, dbTexture)
|
||
|
end
|
||
|
|
||
|
-- arena{1-5}, boss{1-5}
|
||
|
for unit in pairs(self.groupunits) do
|
||
|
UF:FrameGlow_ConfigureGlow(self[unit], unit, dbTexture)
|
||
|
end
|
||
|
|
||
|
-- assist, tank, party, raid, raid40, raidpet
|
||
|
for groupName in pairs(self.headers) do
|
||
|
assert(self[groupName], 'UF FrameGlow: Invalid group specified.')
|
||
|
local group = self[groupName]
|
||
|
|
||
|
if group.GetNumChildren then
|
||
|
for i=1, group:GetNumChildren() do
|
||
|
local frame = select(i, group:GetChildren())
|
||
|
if frame and frame.Health then
|
||
|
UF:FrameGlow_ConfigureGlow(frame, frame.unit, dbTexture)
|
||
|
UF:FrameGlow_CheckChildren(frame, dbTexture)
|
||
|
elseif frame then
|
||
|
for n = 1, frame:GetNumChildren() do
|
||
|
local child = select(n, frame:GetChildren())
|
||
|
if child and child.Health then
|
||
|
UF:FrameGlow_ConfigureGlow(child, child.unit, dbTexture)
|
||
|
UF:FrameGlow_CheckChildren(child, dbTexture)
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end
|