458 lines
15 KiB
Lua
458 lines
15 KiB
Lua
local E, L, V, P, G = unpack(select(2, ...)); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
|
|
local UF = E:GetModule('UnitFrames')
|
|
local NP = E:GetModule('NamePlates')
|
|
|
|
local _G = _G
|
|
local pairs, pcall = pairs, pcall
|
|
local unpack, type, select, getmetatable = unpack, type, select, getmetatable
|
|
local EnumerateFrames = EnumerateFrames
|
|
local hooksecurefunc = hooksecurefunc
|
|
local CreateFrame = CreateFrame
|
|
|
|
local backdropr, backdropg, backdropb, backdropa = 0, 0, 0, 1
|
|
local borderr, borderg, borderb, bordera = 0, 0, 0, 1
|
|
|
|
-- 8.2 restricted frame check
|
|
function E:SetPointsRestricted(frame)
|
|
if frame and not pcall(frame.GetPoint, frame) then
|
|
return true
|
|
end
|
|
end
|
|
|
|
function E:SafeGetPoint(frame)
|
|
if frame and frame.GetPoint and not E:SetPointsRestricted(frame) then
|
|
return frame:GetPoint()
|
|
end
|
|
end
|
|
|
|
local function WatchPixelSnap(frame, snap)
|
|
if (frame and not frame:IsForbidden()) and frame.PixelSnapDisabled and snap then
|
|
frame.PixelSnapDisabled = nil
|
|
end
|
|
end
|
|
|
|
local function DisablePixelSnap(frame)
|
|
if (frame and not frame:IsForbidden()) and not frame.PixelSnapDisabled then
|
|
if frame.SetSnapToPixelGrid then
|
|
frame:SetSnapToPixelGrid(false)
|
|
frame:SetTexelSnappingBias(0)
|
|
elseif frame.GetStatusBarTexture then
|
|
local texture = frame:GetStatusBarTexture()
|
|
if texture and texture.SetSnapToPixelGrid then
|
|
texture:SetSnapToPixelGrid(false)
|
|
texture:SetTexelSnappingBias(0)
|
|
end
|
|
end
|
|
|
|
frame.PixelSnapDisabled = true
|
|
end
|
|
end
|
|
|
|
local function GetTemplate(template, isUnitFrameElement)
|
|
backdropa, bordera = 1, 1
|
|
|
|
if template == 'ClassColor' then
|
|
local color = E:ClassColor(E.myclass)
|
|
borderr, borderg, borderb = color.r, color.g, color.b
|
|
backdropr, backdropg, backdropb = unpack(E.media.backdropcolor)
|
|
elseif template == 'Transparent' then
|
|
borderr, borderg, borderb = unpack(isUnitFrameElement and E.media.unitframeBorderColor or E.media.bordercolor)
|
|
backdropr, backdropg, backdropb, backdropa = unpack(E.media.backdropfadecolor)
|
|
else
|
|
borderr, borderg, borderb = unpack(isUnitFrameElement and E.media.unitframeBorderColor or E.media.bordercolor)
|
|
backdropr, backdropg, backdropb = unpack(E.media.backdropcolor)
|
|
end
|
|
end
|
|
|
|
local function Size(frame, width, height, ...)
|
|
local w = E:Scale(width)
|
|
frame:SetSize(w, (height and E:Scale(height)) or w, ...)
|
|
end
|
|
|
|
local function Width(frame, width, ...)
|
|
frame:SetWidth(E:Scale(width), ...)
|
|
end
|
|
|
|
local function Height(frame, height, ...)
|
|
frame:SetHeight(E:Scale(height), ...)
|
|
end
|
|
|
|
local function Point(obj, arg1, arg2, arg3, arg4, arg5, ...)
|
|
if not arg2 then arg2 = obj:GetParent() end
|
|
|
|
if type(arg2)=='number' then arg2 = E:Scale(arg2) end
|
|
if type(arg3)=='number' then arg3 = E:Scale(arg3) end
|
|
if type(arg4)=='number' then arg4 = E:Scale(arg4) end
|
|
if type(arg5)=='number' then arg5 = E:Scale(arg5) end
|
|
|
|
obj:SetPoint(arg1, arg2, arg3, arg4, arg5, ...)
|
|
end
|
|
|
|
local function SetOutside(obj, anchor, xOffset, yOffset, anchor2, noScale)
|
|
if not anchor then anchor = obj:GetParent() end
|
|
|
|
if not xOffset then xOffset = E.Border end
|
|
if not yOffset then yOffset = E.Border end
|
|
local x = (noScale and xOffset) or E:Scale(xOffset)
|
|
local y = (noScale and yOffset) or E:Scale(yOffset)
|
|
|
|
if E:SetPointsRestricted(obj) or obj:GetPoint() then
|
|
obj:ClearAllPoints()
|
|
end
|
|
|
|
DisablePixelSnap(obj)
|
|
obj:SetPoint('TOPLEFT', anchor, 'TOPLEFT', -x, y)
|
|
obj:SetPoint('BOTTOMRIGHT', anchor2 or anchor, 'BOTTOMRIGHT', x, -y)
|
|
end
|
|
|
|
local function SetInside(obj, anchor, xOffset, yOffset, anchor2, noScale)
|
|
if not anchor then anchor = obj:GetParent() end
|
|
|
|
if not xOffset then xOffset = E.Border end
|
|
if not yOffset then yOffset = E.Border end
|
|
local x = (noScale and xOffset) or E:Scale(xOffset)
|
|
local y = (noScale and yOffset) or E:Scale(yOffset)
|
|
|
|
if E:SetPointsRestricted(obj) or obj:GetPoint() then
|
|
obj:ClearAllPoints()
|
|
end
|
|
|
|
DisablePixelSnap(obj)
|
|
obj:SetPoint('TOPLEFT', anchor, 'TOPLEFT', x, -y)
|
|
obj:SetPoint('BOTTOMRIGHT', anchor2 or anchor, 'BOTTOMRIGHT', -x, y)
|
|
end
|
|
|
|
local function SetTemplate(frame, template, glossTex, ignoreUpdates, forcePixelMode, isUnitFrameElement, isNamePlateElement)
|
|
GetTemplate(template, isUnitFrameElement)
|
|
|
|
frame.template = template or 'Default'
|
|
frame.glossTex = glossTex
|
|
frame.ignoreUpdates = ignoreUpdates
|
|
frame.forcePixelMode = forcePixelMode
|
|
frame.isUnitFrameElement = isUnitFrameElement
|
|
frame.isNamePlateElement = isNamePlateElement
|
|
|
|
if template == 'NoBackdrop' then
|
|
frame:SetBackdrop()
|
|
else
|
|
frame:SetBackdrop({
|
|
edgeFile = E.media.blankTex,
|
|
bgFile = glossTex and (type(glossTex) == 'string' and glossTex or E.media.glossTex) or E.media.blankTex,
|
|
edgeSize = E:Scale(E.twoPixelsPlease and 2 or 1)
|
|
})
|
|
|
|
if frame.callbackBackdropColor then
|
|
frame:callbackBackdropColor()
|
|
else
|
|
frame:SetBackdropColor(backdropr, backdropg, backdropb, frame.customBackdropAlpha or (template == 'Transparent' and backdropa) or 1)
|
|
end
|
|
|
|
local notPixelMode = not isUnitFrameElement and not isNamePlateElement and not E.PixelMode
|
|
local notThinBorders = (isUnitFrameElement and not UF.thinBorders) or (isNamePlateElement and not NP.thinBorders)
|
|
if (notPixelMode or notThinBorders) and not forcePixelMode then
|
|
local backdrop = {
|
|
edgeFile = E.media.blankTex,
|
|
edgeSize = E:Scale(1)
|
|
}
|
|
|
|
if not frame.iborder then
|
|
local border = CreateFrame('Frame', nil, frame, 'BackdropTemplate')
|
|
border:SetBackdrop(backdrop)
|
|
border:SetBackdropBorderColor(0, 0, 0, 1)
|
|
border:SetInside(frame, 1, 1)
|
|
frame.iborder = border
|
|
end
|
|
|
|
if not frame.oborder then
|
|
local border = CreateFrame('Frame', nil, frame, 'BackdropTemplate')
|
|
border:SetBackdrop(backdrop)
|
|
border:SetBackdropBorderColor(0, 0, 0, 1)
|
|
border:SetOutside(frame, 1, 1)
|
|
frame.oborder = border
|
|
end
|
|
end
|
|
end
|
|
|
|
if frame.forcedBorderColors then
|
|
borderr, borderg, borderb, bordera = unpack(frame.forcedBorderColors)
|
|
end
|
|
|
|
frame:SetBackdropBorderColor(borderr, borderg, borderb, bordera)
|
|
|
|
if not frame.ignoreUpdates then
|
|
if frame.isUnitFrameElement then
|
|
E.unitFrameElements[frame] = true
|
|
else
|
|
E.frames[frame] = true
|
|
end
|
|
end
|
|
end
|
|
|
|
local function CreateBackdrop(frame, template, glossTex, ignoreUpdates, forcePixelMode, isUnitFrameElement, isNamePlateElement)
|
|
local parent = (frame.IsObjectType and frame:IsObjectType('Texture') and frame:GetParent()) or frame
|
|
local backdrop = frame.backdrop or CreateFrame('Frame', nil, parent, 'BackdropTemplate')
|
|
if not frame.backdrop then frame.backdrop = backdrop end
|
|
|
|
if forcePixelMode then
|
|
backdrop:SetOutside(frame, E.twoPixelsPlease and 2 or 1, E.twoPixelsPlease and 2 or 1)
|
|
else
|
|
local border = (isUnitFrameElement and UF.BORDER) or (isNamePlateElement and NP.BORDER)
|
|
backdrop:SetOutside(frame, border, border)
|
|
end
|
|
|
|
backdrop:SetTemplate(template, glossTex, ignoreUpdates, forcePixelMode, isUnitFrameElement, isNamePlateElement)
|
|
|
|
local frameLevel = parent.GetFrameLevel and parent:GetFrameLevel()
|
|
local frameLevelMinusOne = frameLevel and (frameLevel - 1)
|
|
if frameLevelMinusOne and (frameLevelMinusOne >= 0) then
|
|
backdrop:SetFrameLevel(frameLevelMinusOne)
|
|
else
|
|
backdrop:SetFrameLevel(0)
|
|
end
|
|
end
|
|
|
|
local function CreateShadow(frame, size, pass)
|
|
if not pass and frame.shadow then return end
|
|
if not size then size = 3 end
|
|
|
|
backdropr, backdropg, backdropb, borderr, borderg, borderb = 0, 0, 0, 0, 0, 0
|
|
|
|
local offset = (E.PixelMode and size) or (size + 1)
|
|
local shadow = CreateFrame('Frame', nil, frame, 'BackdropTemplate')
|
|
shadow:SetFrameLevel(1)
|
|
shadow:SetFrameStrata(frame:GetFrameStrata())
|
|
shadow:SetOutside(frame, offset, offset, nil, true)
|
|
shadow:SetBackdrop({edgeFile = E.Media.Textures.GlowTex, edgeSize = size})
|
|
shadow:SetBackdropColor(backdropr, backdropg, backdropb, 0)
|
|
shadow:SetBackdropBorderColor(borderr, borderg, borderb, 0.9)
|
|
|
|
if pass then
|
|
return shadow
|
|
else
|
|
frame.shadow = shadow
|
|
end
|
|
end
|
|
|
|
local function Kill(object)
|
|
if object.UnregisterAllEvents then
|
|
object:UnregisterAllEvents()
|
|
object:SetParent(E.HiddenFrame)
|
|
else
|
|
object.Show = object.Hide
|
|
end
|
|
|
|
object:Hide()
|
|
end
|
|
|
|
local StripTexturesBlizzFrames = {
|
|
'Inset',
|
|
'inset',
|
|
'InsetFrame',
|
|
'LeftInset',
|
|
'RightInset',
|
|
'NineSlice',
|
|
'BG',
|
|
'border',
|
|
'Border',
|
|
'BorderFrame',
|
|
'bottomInset',
|
|
'BottomInset',
|
|
'bgLeft',
|
|
'bgRight',
|
|
'FilligreeOverlay',
|
|
'PortraitOverlay',
|
|
'ArtOverlayFrame',
|
|
'Portrait',
|
|
'portrait',
|
|
'ScrollFrameBorder',
|
|
}
|
|
|
|
local STRIP_TEX = 'Texture'
|
|
local STRIP_FONT = 'FontString'
|
|
local function StripRegion(which, object, kill, alpha)
|
|
if kill then
|
|
object:Kill()
|
|
elseif which == STRIP_TEX then
|
|
object:SetTexture('')
|
|
object:SetAtlas('')
|
|
elseif which == STRIP_FONT then
|
|
object:SetText('')
|
|
end
|
|
|
|
if alpha then
|
|
object:SetAlpha(0)
|
|
end
|
|
end
|
|
|
|
local function StripType(which, object, kill, alpha)
|
|
if object:IsObjectType(which) then
|
|
StripRegion(which, object, kill, alpha)
|
|
else
|
|
if which == STRIP_TEX then
|
|
local FrameName = object.GetName and object:GetName()
|
|
for _, Blizzard in pairs(StripTexturesBlizzFrames) do
|
|
local BlizzFrame = object[Blizzard] or (FrameName and _G[FrameName..Blizzard])
|
|
if BlizzFrame and BlizzFrame.StripTextures then
|
|
BlizzFrame:StripTextures(kill, alpha)
|
|
end
|
|
end
|
|
end
|
|
|
|
if object.GetNumRegions then
|
|
for i = 1, object:GetNumRegions() do
|
|
local region = select(i, object:GetRegions())
|
|
if region and region.IsObjectType and region:IsObjectType(which) then
|
|
StripRegion(which, region, kill, alpha)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
local function StripTextures(object, kill, alpha)
|
|
StripType(STRIP_TEX, object, kill, alpha)
|
|
end
|
|
|
|
local function StripTexts(object, kill, alpha)
|
|
StripType(STRIP_FONT, object, kill, alpha)
|
|
end
|
|
|
|
local function FontTemplate(fs, font, size, style, skip)
|
|
if not skip then -- ignore updates from UpdateFontTemplates
|
|
fs.font, fs.fontSize, fs.fontStyle = font, size, style
|
|
end
|
|
|
|
fs:SetFont(font or E.media.normFont, size or E.db.general.fontSize, style or E.db.general.fontStyle)
|
|
|
|
if style == 'NONE' then
|
|
fs:SetShadowOffset(1, -0.5)
|
|
fs:SetShadowColor(0, 0, 0, 1)
|
|
else
|
|
fs:SetShadowOffset(0, 0)
|
|
fs:SetShadowColor(0, 0, 0, 0)
|
|
end
|
|
|
|
E.texts[fs] = true
|
|
end
|
|
|
|
local function StyleButton(button, noHover, noPushed, noChecked)
|
|
if button.SetHighlightTexture and not button.hover and not noHover then
|
|
local hover = button:CreateTexture()
|
|
hover:SetInside()
|
|
hover:SetBlendMode('ADD')
|
|
hover:SetColorTexture(1, 1, 1, 0.3)
|
|
button:SetHighlightTexture(hover)
|
|
button.hover = hover
|
|
end
|
|
|
|
if button.SetPushedTexture and not button.pushed and not noPushed then
|
|
local pushed = button:CreateTexture()
|
|
pushed:SetInside()
|
|
pushed:SetBlendMode('ADD')
|
|
pushed:SetColorTexture(0.9, 0.8, 0.1, 0.3)
|
|
button:SetPushedTexture(pushed)
|
|
button.pushed = pushed
|
|
end
|
|
|
|
if button.SetCheckedTexture and not button.checked and not noChecked then
|
|
local checked = button:CreateTexture()
|
|
checked:SetInside()
|
|
checked:SetBlendMode('ADD')
|
|
checked:SetColorTexture(1, 1, 1, 0.3)
|
|
button:SetCheckedTexture(checked)
|
|
button.checked = checked
|
|
end
|
|
|
|
local name = button.GetName and button:GetName()
|
|
local cooldown = name and _G[name..'Cooldown']
|
|
if cooldown then
|
|
cooldown:ClearAllPoints()
|
|
cooldown:SetInside()
|
|
cooldown:SetDrawEdge(false)
|
|
cooldown:SetSwipeColor(0, 0, 0, 1)
|
|
end
|
|
end
|
|
|
|
local CreateCloseButton
|
|
do
|
|
local CloseButtonOnClick = function(btn) btn:GetParent():Hide() end
|
|
local CloseButtonOnEnter = function(btn) if btn.Texture then btn.Texture:SetVertexColor(unpack(E.media.rgbvaluecolor)) end end
|
|
local CloseButtonOnLeave = function(btn) if btn.Texture then btn.Texture:SetVertexColor(1, 1, 1) end end
|
|
CreateCloseButton = function(frame, size, offset, texture, backdrop)
|
|
if frame.CloseButton then return end
|
|
|
|
local CloseButton = CreateFrame('Button', nil, frame)
|
|
CloseButton:Size(size or 16)
|
|
CloseButton:Point('TOPRIGHT', offset or -6, offset or -6)
|
|
if backdrop then
|
|
CloseButton:CreateBackdrop(nil, true)
|
|
end
|
|
|
|
CloseButton.Texture = CloseButton:CreateTexture(nil, 'OVERLAY')
|
|
CloseButton.Texture:SetAllPoints()
|
|
CloseButton.Texture:SetTexture(texture or E.Media.Textures.Close)
|
|
|
|
CloseButton:SetScript('OnClick', CloseButtonOnClick)
|
|
CloseButton:SetScript('OnEnter', CloseButtonOnEnter)
|
|
CloseButton:SetScript('OnLeave', CloseButtonOnLeave)
|
|
|
|
frame.CloseButton = CloseButton
|
|
end
|
|
end
|
|
|
|
local function GetNamedChild(frame, childName, index)
|
|
local name = frame and frame.GetName and frame:GetName()
|
|
if not name or not childName then return nil end
|
|
return _G[name..childName..(index or '')]
|
|
end
|
|
|
|
local function addapi(object)
|
|
local mt = getmetatable(object).__index
|
|
if not object.Size then mt.Size = Size end
|
|
if not object.Point then mt.Point = Point end
|
|
if not object.SetOutside then mt.SetOutside = SetOutside end
|
|
if not object.SetInside then mt.SetInside = SetInside end
|
|
if not object.SetTemplate then mt.SetTemplate = SetTemplate end
|
|
if not object.CreateBackdrop then mt.CreateBackdrop = CreateBackdrop end
|
|
if not object.CreateShadow then mt.CreateShadow = CreateShadow end
|
|
if not object.Kill then mt.Kill = Kill end
|
|
if not object.Width then mt.Width = Width end
|
|
if not object.Height then mt.Height = Height end
|
|
if not object.FontTemplate then mt.FontTemplate = FontTemplate end
|
|
if not object.StripTextures then mt.StripTextures = StripTextures end
|
|
if not object.StripTexts then mt.StripTexts = StripTexts end
|
|
if not object.StyleButton then mt.StyleButton = StyleButton end
|
|
if not object.CreateCloseButton then mt.CreateCloseButton = CreateCloseButton end
|
|
if not object.GetNamedChild then mt.GetNamedChild = GetNamedChild end
|
|
if not object.DisabledPixelSnap and (mt.SetSnapToPixelGrid or mt.SetStatusBarTexture or mt.SetColorTexture or mt.SetVertexColor or mt.CreateTexture or mt.SetTexCoord or mt.SetTexture) then
|
|
if mt.SetSnapToPixelGrid then hooksecurefunc(mt, 'SetSnapToPixelGrid', WatchPixelSnap) end
|
|
if mt.SetStatusBarTexture then hooksecurefunc(mt, 'SetStatusBarTexture', DisablePixelSnap) end
|
|
if mt.SetColorTexture then hooksecurefunc(mt, 'SetColorTexture', DisablePixelSnap) end
|
|
if mt.SetVertexColor then hooksecurefunc(mt, 'SetVertexColor', DisablePixelSnap) end
|
|
if mt.CreateTexture then hooksecurefunc(mt, 'CreateTexture', DisablePixelSnap) end
|
|
if mt.SetTexCoord then hooksecurefunc(mt, 'SetTexCoord', DisablePixelSnap) end
|
|
if mt.SetTexture then hooksecurefunc(mt, 'SetTexture', DisablePixelSnap) end
|
|
mt.DisabledPixelSnap = true
|
|
end
|
|
end
|
|
|
|
local handled = {Frame = true}
|
|
local object = CreateFrame('Frame')
|
|
addapi(object)
|
|
addapi(object:CreateTexture())
|
|
addapi(object:CreateFontString())
|
|
addapi(object:CreateMaskTexture())
|
|
|
|
object = EnumerateFrames()
|
|
while object do
|
|
if not object:IsForbidden() and not handled[object:GetObjectType()] then
|
|
addapi(object)
|
|
handled[object:GetObjectType()] = true
|
|
end
|
|
|
|
object = EnumerateFrames(object)
|
|
end
|
|
|
|
addapi(_G.GameFontNormal) --Add API to `CreateFont` objects without actually creating one
|
|
addapi(CreateFrame('ScrollFrame')) --Hacky fix for issue on 7.1 PTR where scroll frames no longer seem to inherit the methods from the 'Frame' widget
|