--[[ ########################################################## S V U I By: Munglunch ########################################################## LOCALIZED LUA FUNCTIONS ########################################################## ]]-- --[[ GLOBALS ]]-- local _G = _G; local unpack = _G.unpack; local select = _G.select; local pairs = _G.pairs; local type = _G.type; local tostring = _G.tostring; local print = _G.print; local pcall = _G.pcall; local tinsert = _G.tinsert; local string = _G.string; local math = _G.math; local table = _G.table; --[[ STRING METHODS ]]-- local format,find = string.format, string.find; --[[ MATH METHODS ]]-- local floor = math.floor; --[[ TABLE METHODS ]]-- local twipe, tcopy = table.wipe, table.copy; local IsAddOnLoaded = _G.IsAddOnLoaded; local LoadAddOn = _G.LoadAddOn; --BLIZZARD API local InCombatLockdown = _G.InCombatLockdown; local CreateFrame = _G.CreateFrame; --[[ ########################################################## GET ADDON DATA ########################################################## ]]-- local SV = _G["SVUI"]; local L = SV.L local MOD = SV.Skins; if(not MOD) then return end; local NewHook = hooksecurefunc; local Schema = MOD.Schema; local VERSION = MOD.Version; --[[ ########################################################## CORE DATA ########################################################## ]]-- MOD.AddOnQueue = {}; MOD.AddOnEvents = {}; MOD.CustomQueue = {}; MOD.EventListeners = {}; MOD.OnLoadAddons = {}; MOD.SkinnedAddons = {}; MOD.Debugging = false; --[[ ########################################################## CORE FUNCTIONS ########################################################## ]]-- local charming = {"Spiffy", "Pimped Out", "Fancy", "Awesome", "Bad Ass", "Sparkly", "Gorgeous", "Handsome", "Shiny"} local styleMessage = '|cffFFAA00[Skinned]|r |cff00FF77%s|r Is Now %s!' local function ListSkinnedAddons(msg, prefix) for style,_ in pairs(MOD.SkinnedAddons) do local verb = charming[math.random(1,#charming)] SV:AddonMessage(styleMessage:format(style, verb)) end end function MOD:LoadAlert(MainText, Function) self.Alert.Text:SetText(MainText) self.Alert.Accept:SetScript('OnClick', Function) self.Alert:Show() end function MOD:Style(style, fn, ...) local pass, catch = pcall(fn, ...) --self.Debugging = true if(catch and self.Debugging) then SV:HandleError("SKINS", style, catch); return end if(pass and (not style:find("Blizzard")) and not self.SkinnedAddons[style]) then self.SkinnedAddons[style] = true self.AddOnQueue[style] = nil end self.Debugging = false end function MOD:IsAddonReady(addon, ...) if not SV.db.Skins.addons then return end for i = 1, select('#', ...) do local a = select(i, ...) if not a then break end if not IsAddOnLoaded(a) then return false end end return SV.db.Skins.addons[addon] end function MOD:SaveAddonStyle(addon, fn, force, passive, ...) self:DefineEventFunction("PLAYER_ENTERING_WORLD", addon) if(passive) then self:DefineEventFunction("ADDON_LOADED", addon) end for i=1, select("#",...) do local event = select(i,...) if(event) then self:DefineEventFunction(event, addon) end end if(SV.defaults.Skins.addons and SV.defaults.Skins.addons[addon] == nil) then SV.defaults.Skins.addons[addon] = true end if force then fn() else self.AddOnQueue[addon] = fn end end function MOD:SaveBlizzardStyle(addon, fn, force) if force then if(not IsAddOnLoaded(addon)) then LoadAddOn(addon) end fn() else self.OnLoadAddons[addon] = fn end end function MOD:SaveCustomStyle(fn) tinsert(MOD.CustomQueue, fn) end function MOD:DefineEventFunction(addonEvent, addon) if(not addon) then return end if(not self.EventListeners[addonEvent]) then self.EventListeners[addonEvent] = {} end self.EventListeners[addonEvent][addon] = true if(not self[addonEvent]) then self[addonEvent] = function(self, event, ...) for name,fn in pairs(self.AddOnQueue) do if self:IsAddonReady(name) and self.EventListeners[event] and self.EventListeners[event][name] then self:Style(name, fn, event, ...) end end end self:RegisterEvent(addonEvent); end end function MOD:SafeEventRemoval(addon, event) if not self.EventListeners[event] then return end if not self.EventListeners[event][addon] then return end self.EventListeners[event][addon] = nil; local defined = false; for name,_ in pairs(self.EventListeners[event]) do if name then defined = true; break end end if not defined then self:UnregisterEvent(event) end end function MOD:PLAYER_ENTERING_WORLD(event, ...) for addonName,fn in pairs(self.OnLoadAddons) do if(IsAddOnLoaded(addonName)) then self:Style(addonName, fn, event, ...) self.OnLoadAddons[addonName] = nil end end for _,fn in pairs(self.CustomQueue)do fn(event, ...) end twipe(self.CustomQueue) local listener = self.EventListeners[event] for addonName,fn in pairs(self.AddOnQueue)do if(SV.db.Skins.addons[addonName] == nil) then SV.db.Skins.addons[addonName] = true end if(listener[addonName] and self:IsAddonReady(addonName)) then self:Style(addonName, fn, event, ...) end end SV.Events:Trigger("REQUEST_TEMPLATE_UPDATED"); end function MOD:ADDON_LOADED(event, addon) --print(addon) local needsUpdate = false for name, fn in pairs(self.OnLoadAddons) do if(addon:find(name)) then self:Style(name, fn, event, addon) self.OnLoadAddons[name] = nil needsUpdate = true end end local listener = self.EventListeners[event] if(listener) then for name, fn in pairs(self.AddOnQueue) do if(listener[name] and self:IsAddonReady(name)) then self:Style(name, fn, event, addon) needsUpdate = true end end end -- if(addon == 'SVUI_!Options') then -- self:Style(addon, MOD.StyleSVUIOptions) -- end if(needsUpdate) then SV.Events:Trigger("REQUEST_TEMPLATE_UPDATED"); end end --[[ ########################################################## CUSTOM HANDLERS ########################################################## ]]-- local AddonDockletToggle = function(self) if(not MOD.Docklet:IsShown()) then MOD.Docklet:Show() end if(not MOD.Docklet.Dock1:IsShown()) then MOD.Docklet.Dock1:Show() end if(not MOD.Docklet.Dock2:IsShown()) then MOD.Docklet.Dock2:Show() end end local ShowSubDocklet = function(self) local frame = self.FrameLink if(frame and frame.Show) then if(InCombatLockdown() and (frame.IsProtected and frame:IsProtected())) then return end if(not frame:IsShown()) then frame:Show() end end end local HideSubDocklet = function(self) local frame = self.FrameLink if(frame and frame.Hide) then if(InCombatLockdown() and (frame.IsProtected and frame:IsProtected())) then return end if(frame:IsShown()) then frame:Hide() end end end local function DockExpandDocklet(location) if(not location or (location ~= MOD.Docklet.Parent.Bar.Data.Location)) then return end MOD.Docklet:UpdateEmbeds() end local function DockFadeInDocklet(location) if(not location or (location ~= MOD.Docklet.Parent.Bar.Data.Location)) then return end local active = MOD.Docklet.Button.ActiveDocklet if(active) then MOD.Docklet.Dock1:Show() MOD.Docklet.Dock2:Show() end end local function DockFadeOutDocklet(location) if(not location or (location ~= MOD.Docklet.Parent.Bar.Data.Location)) then return end local active = MOD.Docklet.Button.ActiveDocklet if(active) then MOD.Docklet.Dock1:Hide() MOD.Docklet.Dock2:Hide() end end --[[ ########################################################## BUILD FUNCTION ########################################################## ]]-- function MOD:ReLoad() self:RegisterAddonDocklets() end function MOD:Load() SV.private.Docks = SV.private.Docks or {"None", "None"} local alert = CreateFrame('Frame', nil, UIParent); alert:SetStyle("!_Frame", 'Transparent'); alert:SetSize(250, 70); alert:SetPoint('CENTER', UIParent, 'CENTER'); alert:SetFrameStrata('DIALOG'); alert.Text = alert:CreateFontString(nil, "OVERLAY"); alert.Text:SetFont(SV.media.font.dialog, 12); alert.Text:SetPoint('TOP', alert, 'TOP', 0, -10); alert.Accept = CreateFrame('Button', nil, alert); alert.Accept:SetSize(70, 25); alert.Accept:SetPoint('RIGHT', alert, 'BOTTOM', -10, 20); alert.Accept.Text = alert.Accept:CreateFontString(nil, "OVERLAY"); alert.Accept.Text:SetFont(SV.media.font.dialog, 10); alert.Accept.Text:SetPoint('CENTER'); alert.Accept.Text:SetText(_G.YES); alert.Close = CreateFrame('Button', nil, alert); alert.Close:SetSize(70, 25); alert.Close:SetPoint('LEFT', alert, 'BOTTOM', 10, 20); alert.Close:SetScript('OnClick', function(this) this:GetParent():Hide() end); alert.Close.Text = alert.Close:CreateFontString(nil, "OVERLAY"); alert.Close.Text:SetFont(SV.media.font.dialog, 10); alert.Close.Text:SetPoint('CENTER'); alert.Close.Text:SetText(_G.NO); alert.Accept:SetStyle("Button"); alert.Close:SetStyle("Button"); alert:Hide(); self.Alert = alert; self.Docklet = SV.Dock:NewDocklet("BottomRight", "SVUI_SkinsDock", self.TitleID, [[Interface\AddOns\SVUI_Skins\artwork\DOCK-ICON-ADDON]]); --self.Docklet:SetVisibilityCallbacks(false, false); self.Docklet:SetClickCallbacks(AddonDockletToggle, false, self.GetDockables); --SV.Dock.BottomRight.Bar.Button.GetDockOptions = self.GetDockables; local dockWidth = self.Docklet:GetWidth() self.Docklet.Dock1 = CreateFrame("Frame", "SVUI_SkinsDockAddon1", self.Docklet); self.Docklet.Dock1:SetPoint('TOPLEFT', self.Docklet, 'TOPLEFT', -1, 0); self.Docklet.Dock1:SetPoint('BOTTOMLEFT', self.Docklet, 'BOTTOMLEFT', -1, -1); self.Docklet.Dock1:SetWidth(dockWidth); self.Docklet.Dock1:SetScript('OnShow', ShowSubDocklet); self.Docklet.Dock1:SetScript('OnHide', HideSubDocklet); self.Docklet.Dock2 = CreateFrame("Frame", "SVUI_SkinsDockAddon2", self.Docklet); self.Docklet.Dock2:SetPoint('TOPLEFT', self.Docklet.Dock1, 'TOPRIGHT', 0, 0); self.Docklet.Dock2:SetPoint('BOTTOMRIGHT', self.Docklet, 'BOTTOMRIGHT', 1, -1); self.Docklet.Dock2:SetWidth(dockWidth * 0.5); self.Docklet.Dock2:SetScript('OnShow', ShowSubDocklet); self.Docklet.Dock2:SetScript('OnHide', HideSubDocklet); self:SetEmbedHandlers() self.Docklet:Hide() self:RegisterAddonDocklets() self:RegisterEvent("PLAYER_ENTERING_WORLD"); self:RegisterEvent("ADDON_LOADED"); SV:AddSlashCommand("skinned", "List all addons skinned by SVUI", ListSkinnedAddons); SV.Events:On("DOCK_FADE_IN", DockFadeInDocklet, true); SV.Events:On("DOCK_FADE_OUT", DockFadeOutDocklet, true); SV.Events:On("DOCK_EXPANDED", DockExpandDocklet, true); end