local E, L, V, P, G = unpack(select(2, ...)); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB local S = E:GetModule("Skins") --Lua functions local _G = _G local unpack, pairs, ipairs, select, type = unpack, pairs, ipairs, select, type local floor = math.floor local find, format, lower = string.find, string.format, string.lower --WoW API / Variables local IsAddOnLoaded = IsAddOnLoaded local UIPanelWindows = UIPanelWindows local UpdateUIPanelPositions = UpdateUIPanelPositions local hooksecurefunc = hooksecurefunc S.allowBypass = {} S.addonCallbacks = {} S.nonAddonCallbacks = {["CallPriority"] = {}} S.ArrowRotation = { ["up"] = 0, ["down"] = 3.14, ["left"] = 1.57, ["right"] = -1.57, } function S:SetModifiedBackdrop() if self.backdrop then self = self.backdrop end self:SetBackdropBorderColor(unpack(E.media.rgbvaluecolor)) end function S:SetOriginalBackdrop() if self.backdrop then self = self.backdrop end self:SetBackdropBorderColor(unpack(E.media.bordercolor)) end function S:StatusBarColorGradient(bar, value, max, backdrop) local current = (not max and value) or (value and max and max ~= 0 and value/max) if not (bar and current) then return end local r, g, b = E:ColorGradient(current, 0.8,0,0, 0.8,0.8,0, 0,0.8,0) local bg = backdrop or bar.backdrop if bg then bg:SetBackdropColor(r*0.25, g*0.25, b*0.25) end bar:SetStatusBarColor(r, g, b) end function S:HandleButton(button, strip, isDeclineButton, useCreateBackdrop, noSetTemplate) if button == nil then return end if button.isSkinned then return end local buttonName = button.GetName and button:GetName() if buttonName then local left = _G[buttonName.."Left"] local middle = _G[buttonName.."Middle"] local right = _G[buttonName.."Right"] if left then left:SetAlpha(0) end if middle then middle:SetAlpha(0) end if right then right:SetAlpha(0) end end if button.Left then button.Left:SetAlpha(0) end if button.Middle then button.Middle:SetAlpha(0) end if button.Right then button.Right:SetAlpha(0) end if button.Center then button.Center:SetAlpha(0) end if button.SetNormalTexture then button:SetNormalTexture("") end if button.SetHighlightTexture then button:SetHighlightTexture("") end if button.SetPushedTexture then button:SetPushedTexture("") end if button.SetDisabledTexture then button:SetDisabledTexture("") end if strip then button:StripTextures() end if useCreateBackdrop then button:CreateBackdrop(nil, true) elseif not noSetTemplate then button:SetTemplate(nil, true) end button:HookScript("OnEnter", S.SetModifiedBackdrop) button:HookScript("OnLeave", S.SetOriginalBackdrop) if button.UpdateButton then hooksecurefunc(button, "UpdateButton", function(self) self.Left:SetAlpha(0) self.Right:SetAlpha(0) self.Center:SetAlpha(0) end) end button.isSkinned = true end function S:HandleButtonHighlight(frame, r, g, b, a) if frame == nil then return end if not r then r = 0.9 end if not g then g = 0.9 end if not b then b = 0.9 end if not a then a = 0.35 end local highlightTexture if frame.SetHighlightTexture then highlightTexture = frame:GetHighlightTexture() highlightTexture:SetAllPoints(frame) elseif frame.SetTexture then highlightTexture = frame frame:SetAllPoints(frame:GetParent()) elseif frame.HighlightTexture then highlightTexture = frame.HighlightTexture else highlightTexture = frame:CreateTexture(nil, "HIGHLIGHT") highlightTexture:SetAllPoints(frame) frame.HighlightTexture = highlightTexture end highlightTexture:SetTexture(E.Media.Textures.Highlight) highlightTexture:SetVertexColor(r, g, b, a) end function S:HandleScrollBar(frame, horizontal) if frame == nil then return end if frame.backdrop then return end local parent = frame:GetParent() local frameName = frame:GetName() local scrollUpButton, scrollDownButton local thumb = frame.thumbTexture or frame.GetThumbTexture and frame:GetThumbTexture() or _G[format("%s%s", frameName, "ThumbTexture")] if frameName ~= nil then if not horizontal then scrollUpButton = parent.scrollUp or _G[format("%s%s", frameName, "ScrollUpButton")] or _G[format("%s%s", frameName, "UpButton")] or _G[format("%s%s", frameName, "ScrollUp")] scrollDownButton = parent.scrollDown or _G[format("%s%s", frameName, "ScrollDownButton")] or _G[format("%s%s", frameName, "DownButton")] or _G[format("%s%s", frameName, "ScrollDown")] else scrollUpButton = _G[format("%s%s", frameName, "ScrollLeftButton")] or _G[format("%s%s", frameName, "LeftButton")] or _G[format("%s%s", frameName, "ScrollLeft")] scrollDownButton = _G[format("%s%s", frameName, "ScrollRightButton")] or _G[format("%s%s", frameName, "RightButton")] or _G[format("%s%s", frameName, "ScrollRight")] end end if not horizontal then frame:Width(18) else frame:Height(18) end local frameLevel = frame:GetFrameLevel() frame:StripTextures() frame:CreateBackdrop() frame.backdrop:SetAllPoints() frame.backdrop:SetFrameLevel(frameLevel) if scrollUpButton then if not horizontal then scrollUpButton:Point("BOTTOM", frame, "TOP", 0, 1) S:HandleNextPrevButton(scrollUpButton, "up") else scrollUpButton:Point("RIGHT", frame, "LEFT", -1, 0) S:HandleNextPrevButton(scrollUpButton, "left") end end if scrollDownButton then if not horizontal then scrollDownButton:Point("TOP", frame, "BOTTOM", 0, -1) S:HandleNextPrevButton(scrollDownButton, "down") else scrollDownButton:Point("LEFT", frame, "RIGHT", 1, 0) S:HandleNextPrevButton(scrollDownButton, "right") end end if thumb and not thumb.backdrop then if not horizontal then thumb:Size(18, 22) else thumb:Size(22, 18) end thumb:SetTexture() thumb:CreateBackdrop(nil, true, true) thumb.backdrop:SetFrameLevel(frameLevel + 1) thumb.backdrop:SetBackdropColor(0.6, 0.6, 0.6) thumb.backdrop:Point("TOPLEFT", thumb, "TOPLEFT", 2, -2) thumb.backdrop:Point("BOTTOMRIGHT", thumb, "BOTTOMRIGHT", -2, 2) if not frame.thumbTexture then frame.thumbTexture = thumb end end end -- Proportional Scroll Bars local function ReskinScrollBarArrow(frame, direction) S:HandleNextPrevButton(frame, direction) if frame.Texture then frame.Texture:SetAlpha(0) if frame.Overlay then frame.Overlay:SetAlpha(0) end else frame:StripTextures() end end local function ThumbOnEnter(frame) local r, g, b = unpack(E.media.rgbvaluecolor) local thumb = frame.Thumb or frame if thumb.backdrop then thumb.backdrop:SetBackdropColor(r, g, b, .75) end end local function ThumbOnLeave(frame) local r, g, b = unpack(E.media.rgbvaluecolor) local thumb = frame.Thumb or frame if thumb.backdrop and not thumb.__isActive then thumb.backdrop:SetBackdropColor(r, g, b, .25) end end local function ThumbOnMouseDown(frame) local r, g, b = unpack(E.media.rgbvaluecolor) local thumb = frame.Thumb or frame thumb.__isActive = true if thumb.backdrop then thumb.backdrop:SetBackdropColor(r, g, b, .75) end end local function ThumbOnMouseUp(frame) local r, g, b = unpack(E.media.rgbvaluecolor) local thumb = frame.Thumb or frame thumb.__isActive = nil if thumb.backdrop then thumb.backdrop:SetBackdropColor(r, g, b, .25) end end function S:HandleProportionalScroll(frame) assert(frame, 'doesn\'t exist.') frame:StripTextures() ReskinScrollBarArrow(frame.scrollUp, 'up') ReskinScrollBarArrow(frame.scrollDown, 'down') local scrollBar = frame.scrollBar scrollBar:StripTextures() local thumb = scrollBar:GetThumbTexture() if thumb then thumb.Begin:SetAlpha(0) thumb.End:SetAlpha(0) thumb.Middle:SetAlpha(0) thumb:CreateBackdrop('Transparent') thumb.backdrop:SetFrameLevel(thumb:GetFrameLevel()+1) local r, g, b = unpack(E.media.rgbvaluecolor) thumb.backdrop:SetBackdropColor(r, g, b, .25) thumb.backdrop:SetPoint("TOPLEFT", thumb.Begin) thumb.backdrop:SetPoint("BOTTOMRIGHT", thumb.End) thumb:HookScript('OnEnter', ThumbOnEnter) thumb:HookScript('OnLeave', ThumbOnLeave) thumb:HookScript('OnMouseUp', ThumbOnMouseUp) thumb:HookScript('OnMouseDown', ThumbOnMouseDown) end end local tabs = { "LeftDisabled", "MiddleDisabled", "RightDisabled", "Left", "Middle", "Right" } function S:HandleTab(tab, noBackdrop) if (not tab) or (tab.backdrop and not noBackdrop) then return end for _, object in ipairs(tabs) do local tex = _G[tab:GetName()..object] if tex then tex:SetTexture() end end local highlightTex = tab.GetHighlightTexture and tab:GetHighlightTexture() if highlightTex then highlightTex:SetTexture() else tab:StripTextures() end if not noBackdrop then tab:CreateBackdrop() tab.backdrop:Point("TOPLEFT", 10, E.PixelMode and -1 or -3) tab.backdrop:Point("BOTTOMRIGHT", -10, 3) tab:SetHitRectInsets(10, 10, E.PixelMode and 1 or 3, 3) end end function S:HandleTabSystem(tabSystem) if not tabSystem.tabs then return end for _, tab in pairs(tabSystem.tabs) do S:HandleButton(tab) end end local function HandleScrollListButton(button) if button.scrollListButtonsSkinned then return end button.scrollListButtonsSkinned = true local callback = button:GetScrollList().elvSkinCallback if callback then callback(button) end end function S:HandleScrollList(scrollList, skinCallback) if not scrollList.ScrollFrame then return end if not scrollList.elvSkinCallback then S:HandleProportionalScroll(scrollList.ScrollFrame) scrollList.elvSkinCallback = skinCallback if scrollList.isInitialized then for _, button in ipairs(scrollList.ScrollFrame.buttons) do HandleScrollListButton(button) end elseif not scrollList.elvInitHook then scrollList.elvInitHook = true hooksecurefunc(scrollList, "RefreshScrollFrame", function(self) if not self.ScrollFrame.buttons then return end for _, button in ipairs(self.ScrollFrame.buttons) do HandleScrollListButton(button) end end) end end end function S:HandleRotateButton(btn) if btn == nil then return end if btn.isSkinned then return end btn:SetTemplate() btn:Size(btn:GetWidth() - 14, btn:GetHeight() - 14) local normTex = btn:GetNormalTexture() local pushTex = btn:GetPushedTexture() local highlightTex = btn:GetHighlightTexture() normTex:SetInside() normTex:SetTexCoord(0.3, 0.29, 0.3, 0.65, 0.69, 0.29, 0.69, 0.65) pushTex:SetAllPoints(normTex) pushTex:SetTexCoord(0.3, 0.29, 0.3, 0.65, 0.69, 0.29, 0.69, 0.65) highlightTex:SetAllPoints(normTex) highlightTex:SetTexture(1, 1, 1, 0.3) btn.isSkinned = true end function S:HandleEditBox(frame) if frame == nil then return end if frame.backdrop then return end frame:CreateBackdrop() frame.backdrop:SetFrameLevel(frame:GetFrameLevel()) local EditBoxName = frame.GetName and frame:GetName() if EditBoxName then if _G[EditBoxName.."Left"] then _G[EditBoxName.."Left"]:SetAlpha(0) end if _G[EditBoxName.."Middle"] then _G[EditBoxName.."Middle"]:SetAlpha(0) end if _G[EditBoxName.."Right"] then _G[EditBoxName.."Right"]:SetAlpha(0) end if _G[EditBoxName.."Mid"] then _G[EditBoxName.."Mid"]:SetAlpha(0) end if find(EditBoxName, "Silver") or find(EditBoxName, "Copper") then frame.backdrop:Point("BOTTOMRIGHT", -12, -2) end end end function S:HandleDropDownBox(frame, width, direction) if frame == nil then return end if frame.backdrop then return end local FrameName = frame.GetName and frame:GetName() local button = FrameName and _G[FrameName.."Button"] local text = FrameName and _G[FrameName.."Text"] frame:StripTextures() frame:CreateBackdrop() frame.backdrop:SetFrameLevel(frame:GetFrameLevel()) frame.backdrop:Point("TOPLEFT", 20, -3) frame.backdrop:Point("BOTTOMRIGHT", button, "BOTTOMRIGHT", 2, -2) if not width then width = 155 end frame:Width(width) if text then text:ClearAllPoints() text:Point("RIGHT", button, "LEFT", -2, 0) end if button then S:HandleNextPrevButton(button, direction or nil, {1, 0.8, 0}) button:ClearAllPoints() button:Point("RIGHT", frame, "RIGHT", -10, 3) button:Size(16, 16) end end function S:HandleStatusBar(frame, color) if frame == nil then return end frame:SetFrameLevel(frame:GetFrameLevel() + 1) frame:StripTextures() frame:CreateBackdrop("Transparent") frame:SetStatusBarTexture(E.media.normTex) frame:SetStatusBarColor(unpack(color or {.01, .39, .1})) E:RegisterStatusBar(frame) end function S:HandleCheckBox(frame, noBackdrop, noReplaceTextures, forceSaturation) if frame == nil then return end if frame.isSkinned then return end frame:StripTextures() frame.forceSaturation = forceSaturation if noBackdrop then frame:SetTemplate() frame:Size(16) else frame:CreateBackdrop() frame.backdrop:SetInside(nil, 4, 4) end if not noReplaceTextures then if frame.SetCheckedTexture then if E.private.skins.checkBoxSkin then frame:SetCheckedTexture(E.Media.Textures.Melli) local checkedTexture = frame:GetCheckedTexture() checkedTexture:SetVertexColor(1, 0.82, 0, 0.8) checkedTexture:SetInside(frame.backdrop) else frame:SetCheckedTexture("Interface\\Buttons\\UI-CheckBox-Check") if noBackdrop then frame:GetCheckedTexture():SetInside(nil, -4, -4) end end end if frame.SetDisabledCheckedTexture then if E.private.skins.checkBoxSkin then frame:SetDisabledCheckedTexture(E.Media.Textures.Melli) local disabledCheckedTexture = frame:GetDisabledCheckedTexture() disabledCheckedTexture:SetVertexColor(0.6, 0.6, 0.6, 0.8) disabledCheckedTexture:SetInside(frame.backdrop) else frame:SetDisabledCheckedTexture("Interface\\Buttons\\UI-CheckBox-Check-Disabled") if noBackdrop then frame:GetDisabledCheckedTexture():SetInside(nil, -4, -4) end end end if frame.SetDisabledTexture then if E.private.skins.checkBoxSkin then frame:SetDisabledTexture(E.Media.Textures.Melli) local disabledTexture = frame:GetDisabledTexture() disabledTexture:SetVertexColor(0.6, 0.6, 0.6, 0.8) disabledTexture:SetInside(frame.backdrop) else frame:SetDisabledTexture("Interface\\Buttons\\UI-CheckBox-Check-Disabled") if noBackdrop then frame:GetDisabledTexture():SetInside(nil, -4, -4) end end end frame:HookScript("OnDisable", function(checkbox) if not checkbox.SetDisabledTexture then return end if checkbox:GetChecked() then if E.private.skins.checkBoxSkin then checkbox:SetDisabledTexture(E.Media.Textures.Melli) else checkbox:SetDisabledTexture("Interface\\Buttons\\UI-CheckBox-Check-Disabled") end else checkbox:SetDisabledTexture("") end end) hooksecurefunc(frame, "SetNormalTexture", function(checkbox, texPath) if texPath ~= "" then checkbox:SetNormalTexture("") end end) hooksecurefunc(frame, "SetPushedTexture", function(checkbox, texPath) if texPath ~= "" then checkbox:SetPushedTexture("") end end) hooksecurefunc(frame, "SetHighlightTexture", function(checkbox, texPath) if texPath ~= "" then checkbox:SetHighlightTexture("") end end) hooksecurefunc(frame, "SetCheckedTexture", function(checkbox, texPath) if texPath == E.Media.Textures.Melli or texPath == "Interface\\Buttons\\UI-CheckBox-Check" then return end if E.private.skins.checkBoxSkin then checkbox:SetCheckedTexture(E.Media.Textures.Melli) else checkbox:SetCheckedTexture("Interface\\Buttons\\UI-CheckBox-Check") end end) end frame.isSkinned = true end function S:HandleColorSwatch(frame, size) if frame == nil then return end if frame.isSkinned then return end frame:StripTextures() frame:CreateBackdrop("Default") frame.backdrop:SetFrameLevel(frame:GetFrameLevel()) if size then frame:Size(size) end local normalTexture = frame:GetNormalTexture() normalTexture:SetTexture(E.media.blankTex) normalTexture:ClearAllPoints() normalTexture:SetInside(frame.backdrop) frame.isSkinned = true end function S:HandleIcon(icon, parent) parent = parent or icon:GetParent() icon:SetTexCoord(unpack(E.TexCoords)) parent:CreateBackdrop("Default") icon:SetParent(parent.backdrop) parent.backdrop:SetOutside(icon) end function S:HandleBorderIcon(icon, parent) if not icon.Icon then return end parent = parent or icon:GetParent() icon:SetRounded(false) icon:SetBorderTexture(nil) icon.SetBorderTexture = E.noop icon.SetBorderAtlas = E.noop icon:SetOverlayTexture(nil) icon.SetOverlayTexture = E.noop icon.SetOverlayAtlas = E.noop icon.Icon:SetTexCoord(unpack(E.TexCoords)) parent:CreateBackdrop("Default") icon:SetParent(parent.backdrop) parent.backdrop:SetOutside(icon) end function S:HandleItemButton(b, shrinkIcon) if b == nil then return end if b.isSkinned then return end local icon = b.icon or b.IconTexture or b.iconTexture local texture if b:GetName() and _G[b:GetName().."IconTexture"] then icon = _G[b:GetName().."IconTexture"] elseif b:GetName() and _G[b:GetName().."Icon"] then icon = _G[b:GetName().."Icon"] end if icon and icon:GetTexture() then texture = icon:GetTexture() end b:StripTextures() b:CreateBackdrop("Default", true) b:StyleButton() if icon then icon:SetTexCoord(unpack(E.TexCoords)) if shrinkIcon then b.backdrop:SetAllPoints() icon:SetInside(b) else b.backdrop:SetOutside(icon) end icon:SetParent(b.backdrop) if texture then icon:SetTexture(texture) end end b.isSkinned = true end local handleCloseButtonOnEnter = function(btn) if btn.Texture then btn.Texture:SetVertexColor(unpack(E.media.rgbvaluecolor)) end end local handleCloseButtonOnLeave = function(btn) if btn.Texture then btn.Texture:SetVertexColor(1, 1, 1) end end function S:HandleCloseButton(f, point) f:StripTextures() if f:GetNormalTexture() then f:SetNormalTexture("") f.SetNormalTexture = E.noop end if f:GetPushedTexture() then f:SetPushedTexture("") f.SetPushedTexture = E.noop end if not f.Texture then f.Texture = f:CreateTexture(nil, "OVERLAY") f.Texture:Point("CENTER") f.Texture:SetTexture(E.Media.Textures.Close) f.Texture:Size(12, 12) f:HookScript("OnEnter", handleCloseButtonOnEnter) f:HookScript("OnLeave", handleCloseButtonOnLeave) f:SetHitRectInsets(6, 6, 7, 7) end if point then f:Point("TOPRIGHT", point, "TOPRIGHT", 2, 3) end end local sliderOnDisable = function(self) self:GetThumbTexture():SetVertexColor(0.6, 0.6, 0.6, 0.8) end local sliderOnEnable = function(self) self:GetThumbTexture():SetVertexColor(1, 0.82, 0, 0.8) end function S:HandleSliderFrame(frame) if frame == nil then return end local orientation = frame:GetOrientation() frame:StripTextures() frame:SetTemplate() frame:SetThumbTexture(E.Media.Textures.Melli) local thumb = frame:GetThumbTexture() thumb:SetVertexColor(1, 0.82, 0, 0.8) thumb:Size(10) frame:HookScript("OnDisable", sliderOnDisable) frame:HookScript("OnEnable", sliderOnEnable) if orientation == "VERTICAL" then frame:Width(12) else frame:Height(12) for i = 1, frame:GetNumRegions() do local region = select(i, frame:GetRegions()) if region and region:IsObjectType("FontString") then local point, anchor, anchorPoint, x, y = region:GetPoint() if find(anchorPoint, "BOTTOM") then region:Point(point, anchor, anchorPoint, x, y - 4) end end end end end function S:HandleIconSelectionFrame(frame, numIcons, buttonNameTemplate, frameNameOverride) local frameName = frameNameOverride or frame:GetName() --We need override in case Blizzard fucks up the naming (guild bank) local scrollFrame = _G[frameName.."ScrollFrame"] local editBox = _G[frameName.."EditBox"] local okayButton = _G[frameName.."OkayButton"] or _G[frameName.."Okay"] local cancelButton = _G[frameName.."CancelButton"] or _G[frameName.."Cancel"] frame:StripTextures() scrollFrame:StripTextures() editBox:DisableDrawLayer("BACKGROUND") --Removes textures around it frame:CreateBackdrop("Transparent") frame.backdrop:Point("TOPLEFT", frame, "TOPLEFT", 10, -12) frame.backdrop:Point("BOTTOMRIGHT", cancelButton, "BOTTOMRIGHT", 8, -8) S:HandleButton(okayButton) S:HandleButton(cancelButton) S:HandleEditBox(editBox) for i = 1, numIcons do local button = _G[buttonNameTemplate..i] local icon = _G[button:GetName().."Icon"] button:StripTextures() button:SetTemplate("Default") button:StyleButton(nil, true) icon:SetInside() icon:SetTexCoord(unpack(E.TexCoords)) end end function S:HandleNextPrevButton(btn, arrowDir, color, noBackdrop, stipTexts) if btn.isSkinned then return end if not arrowDir then arrowDir = "down" local ButtonName = btn:GetName() and lower(btn:GetName()) if ButtonName then if (find(ButtonName, "left") or find(ButtonName, "prev") or find(ButtonName, "decrement")) then arrowDir = "left" elseif (find(ButtonName, "right") or find(ButtonName, "next") or find(ButtonName, "increment")) then arrowDir = "right" elseif (find(ButtonName, "scrollup") or find(ButtonName, "upbutton") or find(ButtonName, "top") or find(ButtonName, "promote")) then arrowDir = "up" end end end btn:SetHitRectInsets(0, 0, 0, 0) btn:StripTextures() if not noBackdrop then S:HandleButton(btn) end if stipTexts then btn:StripTexts() end btn:SetNormalTexture(E.Media.Textures.ArrowUp) btn:SetPushedTexture(E.Media.Textures.ArrowUp) btn:SetDisabledTexture(E.Media.Textures.ArrowUp) local Normal, Disabled, Pushed = btn:GetNormalTexture(), btn:GetDisabledTexture(), btn:GetPushedTexture() if noBackdrop then btn:Size(20, 20) Disabled:SetVertexColor(.5, .5, .5) btn.Texture = Normal btn:HookScript("OnEnter", handleCloseButtonOnEnter) btn:HookScript("OnLeave", handleCloseButtonOnLeave) else btn:Size(18, 18) Disabled:SetVertexColor(.3, .3, .3) end Normal:SetInside() Pushed:SetInside() Disabled:SetInside() Normal:SetTexCoord(0, 1, 0, 1) Pushed:SetTexCoord(0, 1, 0, 1) Disabled:SetTexCoord(0, 1, 0, 1) Normal:SetRotation(S.ArrowRotation[arrowDir]) Pushed:SetRotation(S.ArrowRotation[arrowDir]) Disabled:SetRotation(S.ArrowRotation[arrowDir]) Normal:SetVertexColor(unpack(color or {1, 1, 1})) btn.isSkinned = true end function S:SetNextPrevButtonDirection(frame, arrowDir) local direction = self.ArrowRotation[(arrowDir or "down")] frame:GetNormalTexture():SetRotation(direction) frame:GetDisabledTexture():SetRotation(direction) frame:GetPushedTexture():SetRotation(direction) end local function collapseSetNormalTexture_Text(self, texture) if texture then if find(texture, "MinusButton", 1, true) or find(texture, "ZoomOutButton", 1, true) then self.collapseText:SetText("-") return elseif find(texture, "PlusButton", 1, true) or find(texture, "ZoomInButton", 1, true) then self.collapseText:SetText("+") return end end self.collapseText:SetText("") end local function collapseSetNormalTexture_Texture(self, texture) if texture then if find(texture, "MinusButton", 1, true) or find(texture, "ZoomOutButton", 1, true) then self:GetNormalTexture():SetTexture(E.Media.Textures.Minus) self:GetPushedTexture():SetTexture(E.Media.Textures.Minus) self:GetDisabledTexture():SetTexture(E.Media.Textures.Minus) return elseif find(texture, "PlusButton", 1, true) or find(texture, "ZoomInButton", 1, true) then self:GetNormalTexture():SetTexture(E.Media.Textures.Plus) self:GetPushedTexture():SetTexture(E.Media.Textures.Plus) self:GetDisabledTexture():SetTexture(E.Media.Textures.Plus) return end end self:GetNormalTexture():SetTexture(0, 0, 0, 0) self:GetPushedTexture():SetTexture(0, 0, 0, 0) self:GetDisabledTexture():SetTexture(0, 0, 0, 0) end function S:HandleCollapseExpandButton(button, defaultState, useFontString, xOffset, yOffset) if button == nil then return end if button.isSkinned then return end if defaultState == "auto" then local texture = button:GetNormalTexture():GetTexture() if find(texture, "MinusButton", 1, true) or find(texture, "ZoomOutButton", 1, true) then defaultState = "-" elseif find(texture, "PlusButton", 1, true) or find(texture, "ZoomInButton", 1, true) then defaultState = "+" end end button:SetNormalTexture("") button:SetPushedTexture("") button:SetHighlightTexture("") button:SetDisabledTexture("") button.SetPushedTexture = E.noop button.SetHighlightTexture = E.noop button.SetDisabledTexture = E.noop if useFontString then button.collapseText = button:CreateFontString(nil, "OVERLAY") button.collapseText:FontTemplate(nil, 22) button.collapseText:Point("LEFT", xOffset or 5, yOffset or 0) button.collapseText:SetText("") if defaultState == "+" then button.collapseText:SetText("+") elseif defaultState == "-" then button.collapseText:SetText("-") end button.SetNormalTexture = collapseSetNormalTexture_Text else local normalTexture = button:GetNormalTexture() normalTexture:Size(16) normalTexture:ClearAllPoints() normalTexture:Point("LEFT", xOffset or 3, yOffset or 0) normalTexture.SetPoint = E.noop local pushedTexture = button:GetPushedTexture() pushedTexture:Size(16) pushedTexture:ClearAllPoints() pushedTexture:Point("LEFT", xOffset or 3, yOffset or 0) pushedTexture.SetPoint = E.noop local disabledTexture = button:GetDisabledTexture() disabledTexture:Size(16) disabledTexture:ClearAllPoints() disabledTexture:Point("LEFT", xOffset or 3, yOffset or 0) disabledTexture.SetPoint = E.noop disabledTexture:SetVertexColor(0.6, 0.6, 0.6) if defaultState == "+" then normalTexture:SetTexture(E.Media.Textures.Plus) pushedTexture:SetTexture(E.Media.Textures.Plus) disabledTexture:SetTexture(E.Media.Textures.Plus) elseif defaultState == "-" then normalTexture:SetTexture(E.Media.Textures.Minus) pushedTexture:SetTexture(E.Media.Textures.Minus) disabledTexture:SetTexture(E.Media.Textures.Minus) end button.SetNormalTexture = collapseSetNormalTexture_Texture end button.isSkinned = true end do -- Handle collapse like retail (including UIPanelButtonTemplate2) local function UpdateCollapseTexture(button, texture) local tex = button:GetNormalTexture() if strfind(texture, "Plus") or strfind(texture, "Closed") then tex:SetTexture(E.Media.Textures.PlusButton) elseif strfind(texture, "Minus") or strfind(texture, "Open") then tex:SetTexture(E.Media.Textures.MinusButton) end end local function UpdatePushedTexture(button) button:GetPushedTexture():SetTexture("") end local function syncPushTexture(button, _, skip) if not skip then local normal = button:GetNormalTexture():GetTexture() button:SetPushedTexture(normal, true) end end function S:HandleCollapseTexture(button, syncPushed) if syncPushed then -- not needed always hooksecurefunc(button, "SetPushedTexture", syncPushTexture) syncPushTexture(button) else button:SetPushedTexture("") hooksecurefunc(button, "SetPushedTexture", UpdatePushedTexture) -- make it permanent end hooksecurefunc(button, 'SetNormalTexture', UpdateCollapseTexture) UpdateCollapseTexture(button, button:GetNormalTexture():GetTexture()) -- Find the button textures that is still present for i = 1, 3 do local region = select(i, button:GetRegions()) if region and region:IsObjectType("Texture") and region:GetTexture() then -- region:GetTexture() nil check so strfind doesn't error if strfind(region:GetTexture(), "Up") then region:Kill() -- Remove the button backdrop texture for good end end end end end function S:ADDON_LOADED(_, addon) S:SkinAce3() if self.allowBypass[addon] then if self.addonCallbacks[addon] then --Fire events to the skins that rely on this addon for index, event in ipairs(self.addonCallbacks[addon].CallPriority) do self.addonCallbacks[addon][event] = nil self.addonCallbacks[addon].CallPriority[index] = nil E.callbacks:Fire(event) end end return end if not E.initialized then return end if self.addonCallbacks[addon] then for index, event in ipairs(self.addonCallbacks[addon].CallPriority) do self.addonCallbacks[addon][event] = nil self.addonCallbacks[addon].CallPriority[index] = nil E.callbacks:Fire(event) end end end local function SetPanelWindowInfo(frame, name, value, igroneUpdate) frame:SetAttribute(name, value) if not igroneUpdate and frame:IsShown() then UpdateUIPanelPositions(frame) end end local UI_PANEL_OFFSET = 7 function S:SetUIPanelWindowInfo(frame, name, value, offset, igroneUpdate) local frameName = frame and frame.GetName and frame:GetName() if not (frameName and UIPanelWindows[frameName]) then return end name = "UIPanelLayout-"..name if name == "UIPanelLayout-width" then value = E:Scale(value or (frame.backdrop and frame.backdrop:GetWidth() or frame:GetWidth())) + (offset or 0) + UI_PANEL_OFFSET end local valueChanged = frame:GetAttribute(name) ~= value if not frame:CanChangeAttribute() then local frameInfo = format("%s-%s", frameName, name) if self.uiPanelQueue[frameInfo] then if not valueChanged then self.uiPanelQueue[frameInfo][3] = nil else self.uiPanelQueue[frameInfo][3] = value self.uiPanelQueue[frameInfo][4] = igroneUpdate end elseif valueChanged then self.uiPanelQueue[frameInfo] = {frame, name, value, igroneUpdate} if not self.inCombat then self.inCombat = true S:RegisterEvent("PLAYER_REGEN_ENABLED") end end elseif valueChanged then SetPanelWindowInfo(frame, name, value, igroneUpdate) end end function S:SetBackdropHitRect(frame, backdrop, clampRect, attempt) if not frame then return end backdrop = backdrop or frame.backdrop if not backdrop then return end local left = frame:GetLeft() local bleft = backdrop:GetLeft() if not left or not bleft then if attempt ~= 10 then E:Delay(0.1, S.SetBackdropHitRect, S, frame, backdrop, clampRect, attempt and attempt + 1 or 1) end return end left = floor(left + 0.5) local right = floor(frame:GetRight() + 0.5) local top = floor(frame:GetTop() + 0.5) local bottom = floor(frame:GetBottom() + 0.5) bleft = floor(bleft + 0.5) local bright = floor(backdrop:GetRight() + 0.5) local btop = floor(backdrop:GetTop() + 0.5) local bbottom = floor(backdrop:GetBottom() + 0.5) left = bleft - left right = right - bright top = top - btop bottom = bbottom - bottom if not frame:CanChangeAttribute() then self.hitRectQueue[frame] = {left, right, top, bottom, clampRect} if not self.inCombat then self.inCombat = true S:RegisterEvent("PLAYER_REGEN_ENABLED") end else frame:SetHitRectInsets(left, right, top, bottom) if clampRect then frame:SetClampRectInsets(left, -right, -top, bottom) end end end function S:PLAYER_REGEN_ENABLED() self.inCombat = nil self:UnregisterEvent("PLAYER_REGEN_ENABLED") for frameInfo, info in pairs(self.uiPanelQueue) do if info[3] then SetPanelWindowInfo(info[1], info[2], info[3], info[4]) end self.uiPanelQueue[frameInfo] = nil end for frame, info in pairs(self.hitRectQueue) do frame:SetHitRectInsets(info[1], info[2], info[3], info[4]) if info[5] then frame:SetClampRectInsets(info[1], info[2], info[3], info[4]) end self.hitRectQueue[frame] = nil end end --Add callback for skin that relies on another addon. --These events will be fired when the addon is loaded. function S:AddCallbackForAddon(addonName, eventName, loadFunc, forceLoad, bypass) if not addonName or type(addonName) ~= "string" then E:Print("Invalid argument #1 to S:AddCallbackForAddon (string expected)") return elseif not eventName or type(eventName) ~= "string" then E:Print("Invalid argument #2 to S:AddCallbackForAddon (string expected)") return elseif not loadFunc or type(loadFunc) ~= "function" then E:Print("Invalid argument #3 to S:AddCallbackForAddon (function expected)") return end if bypass then self.allowBypass[addonName] = true end --Create an event registry for this addon, so that we can fire multiple events when this addon is loaded if not self.addonCallbacks[addonName] then self.addonCallbacks[addonName] = {["CallPriority"] = {}} end if self.addonCallbacks[addonName][eventName] or E.ModuleCallbacks[eventName] or E.InitialModuleCallbacks[eventName] then --Don't allow a registered callback to be overwritten E:Print("Invalid argument #2 to S:AddCallbackForAddon (event name:", eventName, "is already registered, please use a unique event name)") return end --Register loadFunc to be called when event is fired E.RegisterCallback(E, eventName, loadFunc) if forceLoad then E.callbacks:Fire(eventName) else --Insert eventName in this addons' registry self.addonCallbacks[addonName][eventName] = true self.addonCallbacks[addonName].CallPriority[#self.addonCallbacks[addonName].CallPriority + 1] = eventName end end --Add callback for skin that does not rely on a another addon. --These events will be fired when the Skins module is initialized. function S:AddCallback(eventName, loadFunc) if not eventName or type(eventName) ~= "string" then E:Print("Invalid argument #1 to S:AddCallback (string expected)") return elseif not loadFunc or type(loadFunc) ~= "function" then E:Print("Invalid argument #2 to S:AddCallback (function expected)") return end if self.nonAddonCallbacks[eventName] or E.ModuleCallbacks[eventName] or E.InitialModuleCallbacks[eventName] then --Don't allow a registered callback to be overwritten E:Print("Invalid argument #1 to S:AddCallback (event name:", eventName, "is already registered, please use a unique event name)") return end --Add event name to registry self.nonAddonCallbacks[eventName] = true self.nonAddonCallbacks.CallPriority[#self.nonAddonCallbacks.CallPriority + 1] = eventName --Register loadFunc to be called when event is fired E.RegisterCallback(E, eventName, loadFunc) end function S:SkinAce3() S:HookAce3(LibStub("AceGUI-3.0", true)) S:Ace3_SkinTooltip(LibStub("AceConfigDialog-3.0", true)) S:Ace3_SkinTooltip(E.Libs.AceConfigDialog, E.LibsMinor.AceConfigDialog) end function S:Initialize() self.Initialized = true self.db = E.private.skins self.uiPanelQueue = {} self.hitRectQueue = {} S:SkinAce3() --Fire event for all skins that doesn't rely on a Blizzard addon for index, event in ipairs(self.nonAddonCallbacks.CallPriority) do self.nonAddonCallbacks[event] = nil self.nonAddonCallbacks.CallPriority[index] = nil E.callbacks:Fire(event) end --Fire events for Blizzard addons that are already loaded for addon in pairs(self.addonCallbacks) do if IsAddOnLoaded(addon) then for index, event in ipairs(S.addonCallbacks[addon].CallPriority) do self.addonCallbacks[addon][event] = nil self.addonCallbacks[addon].CallPriority[index] = nil E.callbacks:Fire(event) end end end end S:RegisterEvent("ADDON_LOADED") local function InitializeCallback() S:Initialize() end E:RegisterModule(S:GetName(), InitializeCallback)