local E, L, V, P, G = unpack(select(2, ...)) --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB local DT = E:GetModule("DataTexts") --Lua functions local collectgarbage = collectgarbage local floor = math.floor local format = string.format local tinsert, sort = table.insert, table.sort --WoW API / Variables local CopyTable = CopyTable local GetAddOnCPUUsage = GetAddOnCPUUsage local GetAddOnInfo = GetAddOnInfo local GetAddOnMemoryUsage = GetAddOnMemoryUsage local GetFramerate = GetFramerate local GetNetStats = GetNetStats local GetNumAddOns = GetNumAddOns local HideUIPanel = HideUIPanel local IsAddOnLoaded = IsAddOnLoaded local IsModifierKeyDown = IsModifierKeyDown local IsShiftKeyDown = IsShiftKeyDown local PlaySound = PlaySound local ResetCPUUsage = ResetCPUUsage local ShowUIPanel = ShowUIPanel local UpdateAddOnCPUUsage = UpdateAddOnCPUUsage local UpdateAddOnMemoryUsage = UpdateAddOnMemoryUsage local cpuProfiling = GetCVar("scriptProfile") == "1" local int = 5 -- initial delay local statusColors = { "|cff0CD809", "|cffE8DA0F", "|cffFF9000", "|cffD80909" } local enteredFrame local homeLatencyString = "%d ms" local kiloByteString = "%d kb" local megaByteString = "%.2f mb" local memoryTable = {} local cpuTable = {} local lodTable = {} local disabledTable = {} local initialized local function OnEvent(self, event, addonName) if event == "ADDON_LOADED" then if lodTable[addonName] then tinsert(memoryTable, lodTable[addonName]) if cpuProfiling then tinsert(cpuTable, CopyTable(lodTable[addonName])) end lodTable[addonName] = nil elseif disabledTable[addonName] then tinsert(memoryTable, disabledTable[addonName]) if cpuProfiling then tinsert(cpuTable, CopyTable(disabledTable[addonName])) end disabledTable[addonName] = nil end elseif not initialized and (event == "PLAYER_ENTERING_WORLD" or event == "ELVUI_FORCE_RUN") then local _, name, title, enabled, loadable for i = 1, GetNumAddOns() do name, title, _, enabled, loadable = GetAddOnInfo(i) if IsAddOnLoaded(i) then tinsert(memoryTable, {i, title, 0}) if cpuProfiling then tinsert(cpuTable, {i, title, 0}) end elseif loadable then lodTable[name] = {i, title, 0} elseif not enabled then disabledTable[name] = {i, title, 0} end end initialized = true self:UnregisterEvent(event) elseif initialized and event == "ELVUI_FORCE_RUN" then local name for i = 1, GetNumAddOns() do name = GetAddOnInfo(i) if (lodTable[name] or disabledTable[name]) and IsAddOnLoaded(i) then OnEvent(self, "ADDON_LOADED", name) end end end end local function formatMem(memory) if memory > 999 then return format(megaByteString, memory / 1024) else return format(kiloByteString, memory) end end local function sortByMemoryOrCPU(a, b) if a and b then return (a[3] == b[3] and a[2] < b[2]) or a[3] > b[3] end end local function UpdateMemory() UpdateAddOnMemoryUsage() local totalMemory = 0 for i = 1, #memoryTable do memoryTable[i][3] = GetAddOnMemoryUsage(memoryTable[i][1]) totalMemory = totalMemory + memoryTable[i][3] end sort(memoryTable, sortByMemoryOrCPU) return totalMemory end local function UpdateCPU() UpdateAddOnCPUUsage() local totalCPU = 0 for i = 1, #cpuTable do cpuTable[i][3] = GetAddOnCPUUsage(cpuTable[i][1]) totalCPU = totalCPU + cpuTable[i][3] end sort(cpuTable, sortByMemoryOrCPU) return totalCPU end local function ToggleGameMenuFrame() if EscapeMenu:IsShown() then HideUIPanel(EscapeMenu) else ShowUIPanel(EscapeMenu) end end local function OnClick(_, btn) if IsModifierKeyDown() then collectgarbage("collect") ResetCPUUsage() elseif btn == "LeftButton" then ToggleGameMenuFrame() end end local function OnEnter(self) DT:SetupTooltip(self) local totalMemory = UpdateMemory() local _, _, homeLatency = GetNetStats() DT.tooltip:AddDoubleLine(L["Home Latency:"], format(homeLatencyString, homeLatency), 0.69, 0.31, 0.31, 0.84, 0.75, 0.65) if C_CVar.GetBool("allowAddonMemoryUsage") then DT.tooltip:AddDoubleLine(L["Total Memory:"], formatMem(totalMemory), 0.69, 0.31, 0.31, 0.84, 0.75, 0.65) local totalCPU if cpuProfiling then totalCPU = UpdateCPU() DT.tooltip:AddDoubleLine(L["Total CPU:"], format(homeLatencyString, totalCPU), 0.69, 0.31, 0.31, 0.84, 0.75, 0.65) end DT.tooltip:AddLine(" ") local addon, red, green if IsShiftKeyDown() or not cpuProfiling then for i = 1, #memoryTable do addon = memoryTable[i] red = addon[3] / totalMemory green = 1 - red DT.tooltip:AddDoubleLine(addon[2], formatMem(addon[3]), 1, 1, 1, red, green + .5, 0) end else for i = 1, #cpuTable do addon = cpuTable[i] red = addon[3] / totalCPU green = 1 - red DT.tooltip:AddDoubleLine(addon[2], format(homeLatencyString, addon[3]), 1, 1, 1, red, green + .5, 0) end DT.tooltip:AddLine(" ") DT.tooltip:AddLine(L["(Hold Shift) Memory Usage"]) end DT.tooltip:AddLine(L["(Modifer Click) Collect Garbage"]) else DT.tooltip:AddLine(" ") DT.tooltip:AddLine(L["Automatic Client Garbage Collector is currently active"]) DT.tooltip:AddLine(L["This prevents reporting addon memory usage"]) DT.tooltip:AddLine(L["To change behavior use /cvar allowAddonMemoryUsage 1"]) end DT.tooltip:Show() enteredFrame = true end local function OnLeave() enteredFrame = nil DT.tooltip:Hide() end local function OnUpdate(self, t) int = int - t if int < 0 then local framerate = floor(GetFramerate() + 0.5) local _, _, homeLatency = GetNetStats() self.text:SetFormattedText("FPS: %s%d|r MS: %s%d|r", statusColors[framerate >= 30 and 1 or (framerate >= 20 and framerate < 30) and 2 or (framerate >= 10 and framerate < 20) and 3 or 4], framerate, statusColors[homeLatency < 150 and 1 or (homeLatency >= 150 and homeLatency < 300) and 2 or (homeLatency >= 300 and homeLatency < 500) and 3 or 4], homeLatency) int = 1 if enteredFrame then OnEnter(self) end end end DT:RegisterDatatext("System", {"PLAYER_ENTERING_WORLD", "ADDON_LOADED"}, OnEvent, OnUpdate, OnClick, OnEnter, OnLeave, L["System"])