local E, L, V, P, G = unpack(ElvUI); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB local LSM = LibStub("LibSharedMedia-3.0"); --Cache global variables --Lua functions local _G = _G local tonumber, pairs, ipairs, error, unpack, select, tostring = tonumber, pairs, ipairs, error, unpack, select, tostring local assert, print, type, collectgarbage, pcall, date = assert, print, type, collectgarbage, pcall, date local twipe, tinsert, tremove, next = table.wipe, tinsert, tremove, next local floor = floor local format, find, match, strrep, len, sub, gsub = string.format, string.find, string.match, strrep, string.len, string.sub, string.gsub --WoW API / Variables local CreateFrame = CreateFrame local GetCVar = GetCVar local GetFunctionCPUUsage = GetFunctionCPUUsage local GetTalentTabInfo = GetTalentTabInfo local IsAddOnLoaded = IsAddOnLoaded local IsInInstance, GetNumPartyMembers, GetNumRaidMembers = IsInInstance, GetNumPartyMembers, GetNumRaidMembers local RequestBattlefieldScoreData = RequestBattlefieldScoreData local SendAddonMessage = SendAddonMessage local CUSTOM_CLASS_COLORS = CUSTOM_CLASS_COLORS local RAID_CLASS_COLORS = RAID_CLASS_COLORS _, E.myclass = UnitClass("player") -- Constants _, E.myrace = UnitRace("player") _, E.myfaction = UnitFactionGroup("player") -- The E.myfaction may error when in GM mode E.myfaction = E.myfaction or "Others" E.myname = UnitName("player") E.version = GetAddOnMetadata("ElvUI", "Version") E.myrealm = GetRealmName() _, E.wowbuild = GetBuildInfo() E.wowbuild = tonumber(E.wowbuild) E.resolution = GetCVar("gxResolution") E.screenheight = tonumber(match(E.resolution, "%d+x(%d+)")); E.screenwidth = tonumber(match(E.resolution, "(%d+)x+%d")); E.isMacClient = IsMacClient() E.LSM = LSM E["media"] = {} E["frames"] = {} E["unitFrameElements"] = {} E["statusBars"] = {} E["texts"] = {} E["snapBars"] = {} E["RegisteredModules"] = {} E["RegisteredInitialModules"] = {} E["ModuleCallbacks"] = {["CallPriority"] = {}} E["InitialModuleCallbacks"] = {["CallPriority"] = {}} E["valueColorUpdateFuncs"] = {} E.TexCoords = {.08, .92, .08, .92} E.CreditsList = {} E.PixelMode = false E.InversePoints = { TOP = "BOTTOM", BOTTOM = "TOP", TOPLEFT = "BOTTOMLEFT", TOPRIGHT = "BOTTOMRIGHT", LEFT = "RIGHT", RIGHT = "LEFT", BOTTOMLEFT = "TOPLEFT", BOTTOMRIGHT = "TOPRIGHT", CENTER = "CENTER" } E.DispelClasses = { ["PRIEST"] = { ["Magic"] = true, ["Disease"] = true }, ["SHAMAN"] = { ["Poison"] = true, ["Disease"] = true, ["Curse"] = false }, ["PALADIN"] = { ["Poison"] = true, ["Magic"] = true, ["Disease"] = true }, ["MAGE"] = { ["Curse"] = true }, ["DRUID"] = { ["Curse"] = true, ["Poison"] = true }, } E.HealingClasses = { PALADIN = 1, SHAMAN = 3, DRUID = 3, PRIEST = {1, 2} } E.ClassRole = { PALADIN = { [1] = "Caster", [2] = "Tank", [3] = "Melee" }, PRIEST = "Caster", WARLOCK = "Caster", WARRIOR = { [1] = "Melee", [2] = "Melee", [3] = "Tank" }, HUNTER = "Melee", SHAMAN = { [1] = "Caster", [2] = "Melee", [3] = "Caster" }, ROGUE = "Melee", MAGE = "Caster", DRUID = { [1] = "Caster", [2] = "Melee", [3] = "Caster" } } E.DEFAULT_FILTER = { ["CCDebuffs"] = "Whitelist", ["TurtleBuffs"] = "Whitelist", ["PlayerBuffs"] = "Whitelist", ["Blacklist"] = "Blacklist", ["Whitelist"] = "Whitelist", ["RaidDebuffs"] = "Whitelist", } E.noop = function() end local colorizedName function E:ColorizedName(name, colon) local length = len(name) for i = 1, length do local letter = sub(name, i, i) if i == 1 then colorizedName = format("|cffA11313%s", letter) elseif i == 2 then colorizedName = format("%s|r|cffC4C4C4%s", colorizedName, letter) elseif i == length and colon then colorizedName = format("%s%s|r|cffA11313:|r", colorizedName, letter) else colorizedName = colorizedName..letter end end return colorizedName end function E:Print(msg) print(self:ColorizedName("ElvUI", true), msg) end E.PriestColors = { r = 0.99, g = 0.99, b = 0.99 } function E:GetPlayerRole() local assignedRole = UnitGroupRolesAssigned("player") if assignedRole == "NONE" or not assignedRole then if self.HealingClasses[self.myclass] ~= nil and self:CheckTalentTree(self.HealingClasses[E.myclass]) then return "HEALER" elseif E.Role == "Tank" then return "TANK" else return "DAMAGER" end else return assignedRole end end function E:CheckClassColor(r, g, b) r, g, b = floor(r*100+.5)/100, floor(g*100+.5)/100, floor(b*100+.5)/100 local matchFound = false for class, _ in pairs(RAID_CLASS_COLORS) do if(class ~= E.myclass) then local colorTable = class == "PRIEST" and E.PriestColors or (CUSTOM_CLASS_COLORS and CUSTOM_CLASS_COLORS[class] or RAID_CLASS_COLORS[class]) if(colorTable.r == r and colorTable.g == g and colorTable.b == b) then matchFound = true end end end return matchFound end function E:GetColorTable(data) if (not data.r or not data.g or not data.b) then error("Could not unpack color values.") end if data.a then return {data.r, data.g, data.b, data.a} else return {data.r, data.g, data.b} end end function E:UpdateMedia() if (not self.db["general"] or not self.private["general"]) then return end -- Fonts self["media"].normFont = LSM:Fetch("font", self.db["general"].font) self["media"].combatFont = LSM:Fetch("font", self.db["general"].dmgfont) -- Textures self["media"].blankTex = LSM:Fetch("background", "ElvUI Blank") self["media"].normTex = LSM:Fetch("statusbar", self.private["general"].normTex) self["media"].glossTex = LSM:Fetch("statusbar", self.private["general"].glossTex) -- Border Color local border = E.db["general"].bordercolor if self:CheckClassColor(border.r, border.g, border.b) then local classColor = E.myclass == "PRIEST" and E.PriestColors or (CUSTOM_CLASS_COLORS and CUSTOM_CLASS_COLORS[E.myclass] or RAID_CLASS_COLORS[E.myclass]) E.db["general"].bordercolor.r = classColor.r E.db["general"].bordercolor.g = classColor.g E.db["general"].bordercolor.b = classColor.b end self["media"].bordercolor = {border.r, border.g, border.b} -- UnitFrame Border Color border = E.db["unitframe"].colors.borderColor if self:CheckClassColor(border.r, border.g, border.b) then local classColor = E.myclass == "PRIEST" and E.PriestColors or (CUSTOM_CLASS_COLORS and CUSTOM_CLASS_COLORS[E.myclass] or RAID_CLASS_COLORS[E.myclass]) E.db["unitframe"].colors.borderColor.r = classColor.r E.db["unitframe"].colors.borderColor.g = classColor.g E.db["unitframe"].colors.borderColor.b = classColor.b end self["media"].unitframeBorderColor = {border.r, border.g, border.b} -- Backdrop Color self["media"].backdropcolor = E:GetColorTable(self.db["general"].backdropcolor) -- Backdrop Fade Color self["media"].backdropfadecolor = E:GetColorTable(self.db["general"].backdropfadecolor) -- Value Color local value = self.db["general"].valuecolor if self:CheckClassColor(value.r, value.g, value.b) then value = E.myclass == "PRIEST" and E.PriestColors or (CUSTOM_CLASS_COLORS and CUSTOM_CLASS_COLORS[E.myclass] or RAID_CLASS_COLORS[E.myclass]) self.db["general"].valuecolor.r = value.r self.db["general"].valuecolor.g = value.g self.db["general"].valuecolor.b = value.b end self["media"].hexvaluecolor = self:RGBToHex(value.r, value.g, value.b) self["media"].rgbvaluecolor = {value.r, value.g, value.b} if LeftChatPanel and LeftChatPanel.tex and RightChatPanel and RightChatPanel.tex then LeftChatPanel.tex:SetTexture(E.db.chat.panelBackdropNameLeft) local a = E.db.general.backdropfadecolor.a or 0.5 LeftChatPanel.tex:SetAlpha(a) RightChatPanel.tex:SetTexture(E.db.chat.panelBackdropNameRight) RightChatPanel.tex:SetAlpha(a) end self:ValueFuncCall() self:UpdateBlizzardFonts() end local function LSMCallback() E:UpdateMedia() end E.LSM.RegisterCallback(E, "LibSharedMedia_Registered", LSMCallback) local LBF = LibStub("LibButtonFacade", true) local LBFGroupToTableElement = { ["ActionBars"] = "actionbar", ["Auras"] = "auras" } function E:LBFCallback(SkinID, _, _, Group) if not E.private then return end local element = LBFGroupToTableElement[Group] if element then if E.private[element].lbf.enable then E.private[element].lbf.skin = SkinID end end end if LBF then LBF:RegisterSkinCallback("ElvUI", E.LBFCallback, E) end function E:RequestBGInfo() RequestBattlefieldScoreData() end function E:PLAYER_ENTERING_WORLD() if not self.MediaUpdated then self:UpdateMedia() self.MediaUpdated = true -- else -- self:ScheduleTimer("CheckRole", 0.01) end local _, instanceType = IsInInstance() if instanceType == "pvp" then self.BGTimer = self:ScheduleRepeatingTimer("RequestBGInfo", 5) self:RequestBGInfo() elseif self.BGTimer then self:CancelTimer(self.BGTimer) self.BGTimer = nil end end function E:ValueFuncCall() for func, _ in pairs(self["valueColorUpdateFuncs"]) do func(self["media"].hexvaluecolor, unpack(self["media"].rgbvaluecolor)) end end function E:UpdateFrameTemplates() for frame in pairs(self["frames"]) do if(frame and frame.template) then E:SetTemplate(frame, frame.template, frame.glossTex) else self["frames"][frame] = nil end end for frame in pairs(self["unitFrameElements"]) do if frame and frame.template and not frame.ignoreUpdates then E:SetTemplate(frame, frame.template, frame.glossTex) else self["unitFrameElements"][frame] = nil end end end function E:UpdateBorderColors() for frame in pairs(self["frames"]) do if(frame) then if(frame.template == "Default" or frame.template == "Transparent" or frame.template == nil) then frame:SetBackdropBorderColor(unpack(self["media"].bordercolor)) end else self["frames"][frame] = nil end end for frame in pairs(self["unitFrameElements"]) do if frame and not frame.ignoreUpdates then if frame.template == "Default" or frame.template == "Transparent" or frame.template == nil then frame:SetBackdropBorderColor(unpack(self["media"].unitframeBorderColor)) end else self["unitFrameElements"][frame] = nil end end end function E:UpdateBackdropColors() for frame, _ in pairs(self["frames"]) do if(frame) then if(frame.template == "Default" or frame.template == nil) then if(frame.backdropTexture) then frame.backdropTexture:SetVertexColor(unpack(self["media"].backdropcolor)) else frame:SetBackdropColor(unpack(self["media"].backdropcolor)) end elseif(frame.template == "Transparent") then frame:SetBackdropColor(unpack(self["media"].backdropfadecolor)) end else self["frames"][frame] = nil end end for frame, _ in pairs(self["unitFrameElements"]) do if frame then if frame.template == "Default" or frame.template == nil then if frame.backdropTexture then frame.backdropTexture:SetVertexColor(unpack(self["media"].backdropcolor)) else frame:SetBackdropColor(unpack(self["media"].backdropcolor)) end elseif frame.template == "Transparent" then frame:SetBackdropColor(unpack(self["media"].backdropfadecolor)) end else self["unitFrameElements"][frame] = nil end end end function E:UpdateFontTemplates() for text, _ in pairs(self["texts"]) do if text then E:FontTemplate(text, text.font, text.fontSize, text.fontStyle) else self["texts"][text] = nil end end end function E:RegisterStatusBar(statusBar) tinsert(self.statusBars, statusBar) end function E:UpdateStatusBars() for _, statusBar in pairs(self.statusBars) do if(statusBar and statusBar:GetObjectType() == "StatusBar") then statusBar:SetStatusBarTexture(self.media.normTex) elseif(statusBar and statusBar:GetObjectType() == "Texture") then statusBar:SetTexture(self.media.normTex) end end end --This frame everything in ElvUI should be anchored to for Eyefinity support. E.UIParent = CreateFrame("Frame", "ElvUIParent", UIParent) E.UIParent:SetFrameLevel(UIParent:GetFrameLevel()) E.UIParent:SetPoint("CENTER", UIParent, "CENTER") E.UIParent:SetHeight(GetScreenHeight()) E.UIParent:SetWidth(GetScreenWidth()) tinsert(E["snapBars"], E.UIParent) E.HiddenFrame = CreateFrame("Frame") E.HiddenFrame:Hide() function E:IsDispellableByMe(debuffType) if not self.DispelClasses[self.myclass] then return end if self.DispelClasses[self.myclass][debuffType] then return true end end function E:GetTalentSpecInfo() local maxPoints, specIdx, specName, specIcon = 0, 0 for i = 1, 3 do local name, icon, pointsSpent = GetTalentTabInfo(i) if maxPoints < pointsSpent then maxPoints = pointsSpent specIdx = i specName = name specIcon = icon end end if not specName then specName = "None" end if not specIcon then specIcon = "Interface\\Icons\\INV_Misc_QuestionMark" end return specIdx, specName, specIcon end function E:CheckTalentTree(tree) local talentTree = self.TalentTree if not talentTree then return false end if type(tree) == "number" then return tree == talentTree elseif type(tree) == "table" then for _, index in pairs(tree) do return index == talentTree end end end function E:CheckRole() local talentTree = self:GetTalentSpecInfo() local role if type(self.ClassRole[self.myclass]) == "string" then role = self.ClassRole[self.myclass] elseif(talentTree) then if self.myclass == "DRUID" and talentTree == 2 then role = select(5, GetTalentInfo(talentTree, 22)) > 0 and "Tank" or "Melee" else role = self.ClassRole[self.myclass][talentTree] end end if not role then role = "Melee" end if self.Role ~= role then self.Role = role self.TalentTree = talentTree self.callbacks:Fire("RoleChanged") end if E.myclass == "SHAMAN" then if talentTree == 3 then self.DispelClasses[self.myclass].Curse = true else self.DispelClasses[self.myclass].Curse = false end end end function E:IncompatibleAddOn(addon, module) E.PopupDialogs["INCOMPATIBLE_ADDON"].button1 = addon E.PopupDialogs["INCOMPATIBLE_ADDON"].button2 = "ElvUI "..module E.PopupDialogs["INCOMPATIBLE_ADDON"].addon = addon E.PopupDialogs["INCOMPATIBLE_ADDON"].module = module E:StaticPopup_Show("INCOMPATIBLE_ADDON", addon, module) end function E:CheckIncompatible() if E.global.ignoreIncompatible then return end if IsAddOnLoaded("Prat-3.0") and E.private.chat.enable then E:IncompatibleAddOn("Prat-3.0", "Chat") end if IsAddOnLoaded("Chatter") and E.private.chat.enable then E:IncompatibleAddOn("Chatter", "Chat") end if IsAddOnLoaded("SnowfallKeyPress") and E.private.actionbar.enable then E.private.actionbar.keyDown = true E:IncompatibleAddOn("SnowfallKeyPress", "ActionBar") end if IsAddOnLoaded("TidyPlates") and E.private.nameplates.enable then E:IncompatibleAddOn("TidyPlates", "NamePlates") end end function E:IsFoolsDay() if find(date(), "04/01/") and not E.global.aprilFools then return true else return false end end function E:CopyTable(currentTable, defaultTable) if type(currentTable) ~= "table" then currentTable = {} end if type(defaultTable) == "table" then for option, value in pairs(defaultTable) do if type(value) == "table" then value = self:CopyTable(currentTable[option], value) end currentTable[option] = value end end return currentTable end function E:RemoveEmptySubTables(tbl) if type(tbl) ~= "table" then E:Print("Bad argument #1 to 'RemoveEmptySubTables' (table expected)") return end for k, v in pairs(tbl) do if type(v) == "table" then if next(v) == nil then tbl[k] = nil else self:RemoveEmptySubTables(v) end end end end function E:RemoveTableDuplicates(cleanTable, checkTable) if type(cleanTable) ~= "table" then E:Print("Bad argument #1 to 'RemoveTableDuplicates' (table expected)") return end if type(checkTable) ~= "table" then E:Print("Bad argument #2 to 'RemoveTableDuplicates' (table expected)") return end local cleaned = {} for option, value in pairs(cleanTable) do if type(value) == "table" and checkTable[option] and type(checkTable[option]) == "table" then cleaned[option] = self:RemoveTableDuplicates(value, checkTable[option]) else if cleanTable[option] ~= checkTable[option] then cleaned[option] = value end end end self:RemoveEmptySubTables(cleaned) return cleaned end function E:TableToLuaString(inTable) if type(inTable) ~= "table" then E:Print("Invalid argument #1 to E:TableToLuaString (table expected)") return end local ret = "{\n" local function recurse(table, level) for i, v in pairs(table) do ret = ret .. strrep(" ", level).."[" if type(i) == "string" then ret = ret .. "\"" .. i .. "\"" else ret = ret .. i end ret = ret .. "] = " if type(v) == "number" then ret = ret .. v .. ",\n" elseif type(v) == "string" then ret = ret .. "\"" .. gsub(gsub(gsub(v, "\\", "\\\\"), "\n", "\\n"), "\"", "\\\"") .. "\",\n" elseif type(v) == "boolean" then if v then ret = ret .. "true,\n" else ret = ret .. "false,\n" end elseif type(v) == "table" then ret = ret .. "{\n" recurse(v, level + 1) ret = ret .. strrep(" ", level) .. "},\n" else ret = ret .. "\""..tostring(v) .. "\",\n" end end end if inTable then recurse(inTable, 1) end ret = ret.."}" return ret end local profileFormat = { ["profile"] = "E.db", ["private"] = "E.private", ["global"] = "E.global", ["filtersNP"] = "E.global", ["filtersUF"] = "E.global", ["filtersAll"] = "E.global" } local lineStructureTable = {} function E:ProfileTableToPluginFormat(inTable, profileType) local profileText = profileFormat[profileType] if not profileText then return end twipe(lineStructureTable) local returnString = "" local lineStructure = "" local sameLine = false local function buildLineStructure() local str = profileText for _, v in ipairs(lineStructureTable) do if(type(v) == "string") then str = str .. "[\"" .. v .. "\"]" else str = str .. "[" .. v .. "]" end end return str end local function recurse(tbl) lineStructure = buildLineStructure() for k, v in pairs(tbl) do if not sameLine then returnString = returnString .. lineStructure end returnString = returnString .. "[" if type(k) == "string" then returnString = returnString.."\"" .. k .. "\"" else returnString = returnString .. k end if type(v) == "table" then tinsert(lineStructureTable, k) sameLine = true returnString = returnString .. "]" recurse(v) else sameLine = false returnString = returnString .. "] = " if type(v) == "number" then returnString = returnString .. v .. "\n" elseif type(v) == "string" then returnString = returnString .. "\"" .. gsub(gsub(gsub(v, "\\", "\\\\"), "\n", "\\n"), "\"", "\\\"") .. "\"\n" elseif type(v) == "boolean" then if v then returnString = returnString .. "true\n" else returnString = returnString .. "false\n" end else returnString = returnString .. "\"" .. tostring(v) .. "\"\n" end end end tremove(lineStructureTable) lineStructure = buildLineStructure() end if inTable and profileType then recurse(inTable) end return returnString end function E:StringSplitMultiDelim(s, delim) assert(type (delim) == "string" and len(delim) > 0, "bad delimiter") local start = 1 local t = {} while true do local pos = find(s, delim, start, true) if not pos then break end tinsert(t, sub(s, start, pos - 1)) start = pos + len(delim) end tinsert(t, sub(s, start)) return unpack(t) end function E:SendMessage() local numParty, numRaid = GetNumPartyMembers(), GetNumRaidMembers() local inInstance, instanceType = IsInInstance() if inInstance and (instanceType == "pvp") then SendAddonMessage("ELVUI_VERSIONCHK", E.version, "BATTLEGROUND") else if numRaid > 0 then SendAddonMessage("ELVUI_VERSIONCHK", E.version, "RAID") elseif numParty > 0 then SendAddonMessage("ELVUI_VERSIONCHK", E.version, "PARTY") end end if E.SendMSGTimer then self:CancelTimer(E.SendMSGTimer) E.SendMSGTimer = nil end end local SendRecieveGroupSize local function SendRecieve() if not E.global.general.versionCheck then return end if event == "CHAT_MSG_ADDON" then if arg1 ~= "ELVUI_VERSIONCHK" then return end if not arg4 or arg4 == E.myname or E.recievedOutOfDateMessage then return end arg2 = tonumber(arg2) if arg2 and arg2 > tonumber(E.version) then E:Print(L["ElvUI is out of date. You can download the newest version from https://github.com/ElvUI-Vanilla/ElvUI/"]) if (arg2 - tonumber(E.version)) >= 0.05 then E:StaticPopup_Show("ELVUI_UPDATE_AVAILABLE") end E.recievedOutOfDateMessage = true end else local numRaid, numParty = GetNumRaidMembers(), GetNumPartyMembers() + 1 local num = numRaid > 0 and numRaid or numParty if num ~= SendRecieveGroupSize then if num > 1 and SendRecieveGroupSize and num > SendRecieveGroupSize then E.SendMSGTimer = E:ScheduleTimer("SendMessage", 12) end SendRecieveGroupSize = num end end end local f = CreateFrame("Frame") f:RegisterEvent("RAID_ROSTER_UPDATE") f:RegisterEvent("PARTY_MEMBERS_CHANGED") f:RegisterEvent("CHAT_MSG_ADDON") f:SetScript("OnEvent", SendRecieve) function E:UpdateAll(ignoreInstall) self.private = self.charSettings.profile self.db = self.data.profile self.global = self.data.global self.db.theme = nil self.db.install_complete = nil self:SetMoversPositions() self:UpdateMedia() self:UpdateCooldownSettings() local UF = self:GetModule("UnitFrames") UF.db = self.db.unitframe UF:Update_AllFrames() local CH = self:GetModule("Chat") CH.db = self.db.chat CH:PositionChat(true) CH:SetupChat() CH:UpdateAnchors() local AB = self:GetModule("ActionBars") AB.db = self.db.actionbar AB:UpdateButtonSettings() AB:UpdateMicroPositionDimensions() local bags = E:GetModule("Bags") bags.db = self.db.bags bags:Layout() bags:Layout(true) bags:SizeAndPositionBagBar() bags:UpdateItemLevelDisplay() bags:UpdateCountDisplay() self:GetModule("Layout"):ToggleChatPanels() local DT = self:GetModule("DataTexts") DT.db = self.db.datatexts DT:LoadDataTexts() local NP = self:GetModule("NamePlates") NP.db = self.db.nameplates NP:ConfigureAll() local DataBars = self:GetModule("DataBars") DataBars.db = E.db.databars DataBars:UpdateDataBarDimensions() DataBars:EnableDisable_ExperienceBar() DataBars:EnableDisable_ReputationBar() self:GetModule("Auras").db = self.db.auras self:GetModule("Tooltip").db = self.db.tooltip if(ElvUIPlayerBuffs) then E:GetModule("Auras"):UpdateHeader(ElvUIPlayerBuffs) end if(ElvUIPlayerDebuffs) then E:GetModule("Auras"):UpdateHeader(ElvUIPlayerDebuffs) end if not (self.private.install_complete or ignoreInstall) then self:Install() end self:GetModule("Minimap"):UpdateSettings() self:GetModule("AFK"):Toggle() self:UpdateBorderColors() self:UpdateBackdropColors() self:UpdateFrameTemplates() self:UpdateStatusBars() local LO = E:GetModule("Layout") LO:ToggleChatPanels() LO:BottomPanelVisibility() LO:TopPanelVisibility() LO:SetDataPanelStyle() self:GetModule("Blizzard"):SetWatchFrameHeight() end function E:ResetAllUI() self:ResetMovers() if(E.db.lowresolutionset) then E:SetupResolution(true) end if(E.db.layoutSet) then E:SetupLayout(E.db.layoutSet, true) end end function E:ResetUI(name) if(name == "" or name == " " or name == nil) then E:StaticPopup_Show("RESETUI_CHECK") return end self:ResetMovers(name) end function E:RegisterModule(name, loadFunc) --New method using callbacks if (loadFunc and type(loadFunc) == "function") then if self.initialized then loadFunc() else if self.ModuleCallbacks[name] then --Don't allow a registered module name to be overwritten E:Print("Invalid argument #1 to E:RegisterModule (module name:", name, "is already registered, please use a unique name)") return end --Add module name to registry self.ModuleCallbacks[name] = true tinsert(self.ModuleCallbacks["CallPriority"], name) --Register loadFunc to be called when event is fired E:RegisterCallback(name, loadFunc, E:GetModule(name)) end --Old deprecated initialize method else if self.initialized then self:GetModule(name):Initialize() else tinsert(self["RegisteredModules"], name) end end end function E:RegisterInitialModule(name, loadFunc) --New method using callbacks if loadFunc and type(loadFunc) == "function" then if self.InitialModuleCallbacks[name] then --Don't allow a registered module name to be overwritten E:Print("Invalid argument #1 to E:RegisterInitialModule (module name:", name, "is already registered, please use a unique name)") return end --Add module name to registry self.InitialModuleCallbacks[name] = true tinsert(self.InitialModuleCallbacks["CallPriority"], name) --Register loadFunc to be called when event is fired E:RegisterCallback(name, loadFunc, E:GetModule(name)) --Old deprecated initialize method else tinsert(self["RegisteredInitialModules"], name) end end function E:InitializeInitialModules() --Fire callbacks for any module using the new system for index, moduleName in ipairs(self.InitialModuleCallbacks["CallPriority"]) do self.InitialModuleCallbacks[moduleName] = nil self.InitialModuleCallbacks["CallPriority"][index] = nil E.callbacks:Fire(moduleName) end --Old deprecated initialize method, we keep it for any plugins that may need it for _, module in pairs(E["RegisteredInitialModules"]) do module = self:GetModule(module, true) if module and module.Initialize then local _, catch = pcall(module.Initialize, module) if catch and GetCVar("ShowErrors") == "1" then ScriptErrorsFrame_OnError(catch, false) end end end end function E:RefreshModulesDB() local UF = self:GetModule("UnitFrames") twipe(UF.db) UF.db = self.db.unitframe end function E:InitializeModules() --Fire callbacks for any module using the new system for index, moduleName in ipairs(self.ModuleCallbacks["CallPriority"]) do self.ModuleCallbacks[moduleName] = nil self.ModuleCallbacks["CallPriority"][index] = nil E.callbacks:Fire(moduleName) end --Old deprecated initialize method, we keep it for any plugins that may need it for _, module in pairs(E["RegisteredModules"]) do module = self:GetModule(module) if module.Initialize then local _, catch = pcall(module.Initialize, module) if catch and GetCVar("ShowErrors") == "1" then ScriptErrorsFrame_OnError(catch, false) end end end end --DATABASE CONVERSIONS function E:DBConversions() -- Add conversions here end local CPU_USAGE = {} local function CompareCPUDiff(showall, module, minCalls) local greatestUsage, greatestCalls, greatestName, newName, newFunc local greatestDiff, lastModule, mod, newUsage, calls, differance = 0 for name, oldUsage in pairs(CPU_USAGE) do newName, newFunc = match(name, "^([^:]+):(.+)$") if not newFunc then E:Print("CPU_USAGE:", name, newFunc) else if newName ~= lastModule then mod = E:GetModule(newName, true) or E lastModule = newName end newUsage, calls = GetFunctionCPUUsage(mod[newFunc], true) differance = newUsage - oldUsage if showall and calls > minCalls then E:Print(calls, name, differance) end if (differance > greatestDiff) and calls > minCalls then greatestName, greatestUsage, greatestCalls, greatestDiff = name, newUsage, calls, differance end end end if greatestName then E:Print(greatestName .. " had the CPU usage difference of: " .. greatestUsage .. "ms. And has been called " .. greatestCalls .. " times.") else E:Print("CPU Usage: No CPU Usage differences found.") end end function E:GetTopCPUFunc(msg) local module, showall, delay, minCalls = match(msg, "^([^%s]+)%s*([^%s]*)%s*([^%s]*)%s*(.*)$") local mod module = (module == "nil" and nil) or module if not module then E:Print("cpuusage: module (arg1) is required! This can be set as 'all' too.") return end showall = (showall == "true" and true) or false delay = (delay == "nil" and nil) or tonumber(delay) or 5 minCalls = (minCalls == "nil" and nil) or tonumber(minCalls) or 15 twipe(CPU_USAGE) if module == "all" then for _, registeredModule in pairs(self["RegisteredModules"]) do mod = self:GetModule(registeredModule, true) or self for name in pairs(mod) do if type(mod[name]) == "function" and name ~= "GetModule" then CPU_USAGE[registeredModule .. ":" .. name] = GetFunctionCPUUsage(mod[name], true) end end end else mod = self:GetModule(module, true) or self for name in pairs(mod) do if type(mod[name]) == "function" and name ~= "GetModule" then CPU_USAGE[module .. ":" .. name] = GetFunctionCPUUsage(mod[name], true) end end end self:Delay(delay, CompareCPUDiff, showall, module, minCalls) self:Print("Calculating CPU Usage differences (module: " .. (module or "?") .. ", showall: " .. tostring(showall) .. ", minCalls: " .. tostring(minCalls) .. ", delay: " .. tostring(delay) .. ")") end function E:Initialize() twipe(self.db) twipe(self.global) twipe(self.private) self.data = LibStub("AceDB-3.0"):New("ElvDB", self.DF) self.data.RegisterCallback(self, "OnProfileChanged", "UpdateAll") self.data.RegisterCallback(self, "OnProfileCopied", "UpdateAll") self.data.RegisterCallback(self, "OnProfileReset", "OnProfileReset") self.charSettings = LibStub("AceDB-3.0"):New("ElvPrivateDB", self.privateVars) self.private = self.charSettings.profile self.db = self.data.profile self.global = self.data.global self:CheckIncompatible() self:DBConversions() -- self:ScheduleTimer("CheckRole", 0.01) self:UIScale("PLAYER_LOGIN") self:LoadCommands() self:InitializeModules() self:LoadMovers() self:UpdateCooldownSettings() self.initialized = true if self.private.install_complete == nil then self:Install() end if not find(date(), "04/01/") then E.global.aprilFools = nil end --if(self:HelloKittyFixCheck()) then -- self:HelloKittyFix() --end self:UpdateMedia() self:UpdateFrameTemplates() --self:RegisterEvent("ACTIVE_TALENT_GROUP_CHANGED", "CheckRole") -- self:RegisterEvent("CHARACTER_POINTS_CHANGED", "CheckRole") self:RegisterEvent("UPDATE_FLOATING_CHAT_WINDOWS", "UIScale") self:RegisterEvent("PLAYER_ENTERING_WORLD") if self.db.general.kittys then self:CreateKittys() self:Delay(5, self.Print, self, L["Type /hellokitty to revert to old settings."]) end self:Tutorials() self:GetModule("Minimap"):UpdateSettings() self:RefreshModulesDB() collectgarbage() if self.db.general.loginmessage then print(select(2, E:GetModule("Chat"):FindURL("CHAT_MSG_DUMMY", format(L["LOGIN_MSG"], self["media"].hexvaluecolor, self["media"].hexvaluecolor, self.version)))..".") end end