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