local E, L, V, P, G = unpack(ElvUI) local UF = E:GetModule('UnitFrames') local NP = E:GetModule('NamePlates') local _G = _G local pairs, pcall, unpack = pairs, pcall, unpack local strsub, type, next = strsub, type, next local hooksecurefunc = hooksecurefunc local getmetatable = getmetatable local EnumerateFrames = EnumerateFrames 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 type(texture) == 'table' and texture.SetSnapToPixelGrid then texture:SetSnapToPixelGrid(false) texture:SetTexelSnappingBias(0) end end frame.PixelSnapDisabled = true end end local function FixStatusBarMinCurPlease(frame, value) local MIN = frame:GetMinMaxValues() if MIN and (value <= MIN) then -- gg blizz, idk how you manage this one lol local style = frame:GetFillStyle() if style ~= 'STANDARD' and style ~= 'REVERSE' then return end local width, height = frame:GetSize() if not width or not height then return end local texture = frame:GetStatusBarTexture() if not texture then return end texture:ClearAllPoints() local reverse = frame:GetReverseFill() local orientation = frame:GetOrientation() if orientation == 'VERTICAL' then if reverse then texture:SetPoint('TOPLEFT', 0, 0) texture:SetPoint('TOPRIGHT', 0, 0) texture:SetPoint('BOTTOMLEFT', 0, height) texture:SetPoint('BOTTOMRIGHT', 0, height) else texture:SetPoint('TOPLEFT', 0, -height) texture:SetPoint('TOPRIGHT', 0, -height) texture:SetPoint('BOTTOMLEFT', 0, 0) texture:SetPoint('BOTTOMRIGHT', 0, 0) end else -- horizontal if reverse then texture:SetPoint('TOPLEFT', width, 0) texture:SetPoint('TOPRIGHT', 0, 0) texture:SetPoint('BOTTOMLEFT', width, 0) texture:SetPoint('BOTTOMRIGHT', 0, 0) else texture:SetPoint('TOPLEFT', 0, 0) texture:SetPoint('TOPRIGHT', -width, 0) texture:SetPoint('BOTTOMLEFT', 0, 0) texture:SetPoint('BOTTOMRIGHT', -width, 0) end end end end local function FixMinCurDuringValue(frame, value) FixStatusBarMinCurPlease(frame, value) end local function FixMinCurDuringTexture(frame) DisablePixelSnap(frame) FixStatusBarMinCurPlease(frame, frame:GetValue()) end local function BackdropFrameLevel(frame, level) frame:SetFrameLevel(level) if frame.oborder then frame.oborder:SetFrameLevel(level) end if frame.iborder then frame.iborder:SetFrameLevel(level) end end local function BackdropFrameLower(backdrop, parent) local level = parent:GetFrameLevel() local minus = level and (level - 1) if minus and (minus >= 0) then BackdropFrameLevel(backdrop, minus) else BackdropFrameLevel(backdrop, 0) 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, noScale) GetTemplate(template, isUnitFrameElement) frame.template = template or 'Default' frame.glossTex = glossTex frame.ignoreUpdates = ignoreUpdates frame.forcePixelMode = forcePixelMode frame.isUnitFrameElement = isUnitFrameElement frame.isNamePlateElement = isNamePlateElement if not frame.SetBackdrop then _G.Mixin(frame, _G.BackdropTemplateMixin) frame:HookScript('OnSizeChanged', frame.OnBackdropSizeChanged) end if template == 'NoBackdrop' then frame:SetBackdrop() else local edgeSize = E.twoPixelsPlease and 2 or 1 frame:SetBackdrop({ edgeFile = E.media.blankTex, bgFile = glossTex and (type(glossTex) == 'string' and glossTex or E.media.glossTex) or E.media.blankTex, edgeSize = noScale and edgeSize or E:Scale(edgeSize) }) 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 = noScale and 1 or E:Scale(1) } local level = frame:GetFrameLevel() if not frame.iborder then local border = CreateFrame('Frame', nil, frame, 'BackdropTemplate') border:SetBackdrop(backdrop) border:SetBackdropBorderColor(0, 0, 0, 1) border:SetFrameLevel(level) border:SetInside(frame, 1, 1, nil, noScale) 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:SetFrameLevel(level) border:SetOutside(frame, 1, 1, nil, noScale) 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, noScale, allPoints, frameLevel) local parent = (frame.IsObjectType and frame:IsObjectType('Texture') and frame:GetParent()) or frame local backdrop = frame.backdrop or CreateFrame('Frame', nil, parent) if not frame.backdrop then frame.backdrop = backdrop end backdrop:SetTemplate(template, glossTex, ignoreUpdates, forcePixelMode, isUnitFrameElement, isNamePlateElement, noScale) if allPoints then if allPoints == true then backdrop:SetAllPoints() else backdrop:SetAllPoints(allPoints) end else if forcePixelMode then backdrop:SetOutside(frame, E.twoPixelsPlease and 2 or 1, E.twoPixelsPlease and 2 or 1, nil, noScale) else local border = (isUnitFrameElement and UF.BORDER) or (isNamePlateElement and NP.BORDER) backdrop:SetOutside(frame, border, border, nil, noScale) end end if frameLevel then if frameLevel == true then BackdropFrameLevel(backdrop, parent:GetFrameLevel()) else BackdropFrameLevel(backdrop, frameLevel) end else BackdropFrameLower(backdrop, parent) 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 StripTexturesBlizzFrames = { 'Inset', 'inset', 'InsetFrame', 'LeftInset', 'RightInset', 'NineSlice', 'BG', 'border', 'Border', 'BorderFrame', 'bottomInset', 'BottomInset', 'bgLeft', 'bgRight', 'FilligreeOverlay', 'PortraitOverlay', 'ArtOverlayFrame', 'Portrait', 'portrait', 'ScrollFrameBorder', } local function KillEditMode(object) object.HighlightSystem = E.noop object.ClearHighlight = E.noop 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 STRIP_TEX = 'Texture' local STRIP_FONT = 'FontString' local function StripRegion(which, object, kill, zero) if kill then object:Kill() elseif zero then object:SetAlpha(0) elseif which == STRIP_TEX then object:SetTexture(E.ClearTexture) object:SetAtlas('') elseif which == STRIP_FONT then object:SetText('') end end local function StripType(which, object, kill, zero) if object:IsObjectType(which) then StripRegion(which, object, kill, zero) 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, zero) end end end if object.GetNumRegions then for _, region in next, { object:GetRegions() } do if region and region.IsObjectType and region:IsObjectType(which) then StripRegion(which, region, kill, zero) end end end end end local function StripTextures(object, kill, zero) StripType(STRIP_TEX, object, kill, zero) end local function StripTexts(object, kill, zero) StripType(STRIP_FONT, object, kill, zero) 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 -- grab values from profile before conversion if not style then style = E.db.general.fontStyle or P.general.fontStyle end if not size then size = E.db.general.fontSize or P.general.fontSize end if style and strsub(style, 0, 6) == 'SHADOW' then style = strsub(style, 7) -- shadow isnt a real style fs:SetShadowOffset(1, -1) fs:SetShadowColor(0, 0, 0, style == '' and 1 or 0.6) else fs:SetShadowOffset(0, 0) fs:SetShadowColor(0, 0, 0, 0) end if style == 'NONE' or not style then style = '' -- none isnt a real style end fs:SetFont(font or E.media.normFont, size, style) E.texts[fs] = true end local function StyleButton(button, noHover, noPushed, noChecked) if button.SetHighlightTexture and button.CreateTexture 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 button.CreateTexture 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 button.CreateTexture 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 if button.cooldown then button.cooldown:SetDrawEdge(false) button.cooldown:SetInside(button, 0, 0) 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 mk = getmetatable(object).__index if not object.Size then mk.Size = Size end if not object.Point then mk.Point = Point end if not object.SetOutside then mk.SetOutside = SetOutside end if not object.SetInside then mk.SetInside = SetInside end if not object.SetTemplate then mk.SetTemplate = SetTemplate end if not object.CreateBackdrop then mk.CreateBackdrop = CreateBackdrop end if not object.CreateShadow then mk.CreateShadow = CreateShadow end if not object.KillEditMode then mk.KillEditMode = KillEditMode end if not object.Kill then mk.Kill = Kill end if not object.Width then mk.Width = Width end if not object.Height then mk.Height = Height end if not object.FontTemplate then mk.FontTemplate = FontTemplate end if not object.StripTextures then mk.StripTextures = StripTextures end if not object.StripTexts then mk.StripTexts = StripTexts end if not object.StyleButton then mk.StyleButton = StyleButton end if not object.CreateCloseButton then mk.CreateCloseButton = CreateCloseButton end if not object.GetNamedChild then mk.GetNamedChild = GetNamedChild end if not object.DisabledPixelSnap and (mk.SetSnapToPixelGrid or mk.SetStatusBarTexture or mk.SetColorTexture or mk.SetVertexColor or mk.CreateTexture or mk.SetTexCoord or mk.SetTexture) then if mk.SetSnapToPixelGrid then hooksecurefunc(mk, 'SetSnapToPixelGrid', WatchPixelSnap) end if mk.SetColorTexture then hooksecurefunc(mk, 'SetColorTexture', DisablePixelSnap) end if mk.SetVertexColor then hooksecurefunc(mk, 'SetVertexColor', DisablePixelSnap) end if mk.CreateTexture then hooksecurefunc(mk, 'CreateTexture', DisablePixelSnap) end if mk.SetTexCoord then hooksecurefunc(mk, 'SetTexCoord', DisablePixelSnap) end if mk.SetTexture then hooksecurefunc(mk, 'SetTexture', DisablePixelSnap) end if not E.Retail and mk.SetStatusBarTexture then hooksecurefunc(mk, 'SetStatusBarTexture', DisablePixelSnap) end mk.DisabledPixelSnap = true end if E.Retail and not object.fixTheStatusBarsPlease and mk.SetStatusBarTexture then hooksecurefunc(mk, 'SetValue', FixMinCurDuringValue) hooksecurefunc(mk, 'SetStatusBarTexture', FixMinCurDuringTexture) object.fixTheStatusBarsPlease = 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 local objType = object:GetObjectType() if not object:IsForbidden() and not handled[objType] then addapi(object) handled[objType] = 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