You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
795 lines
23 KiB
795 lines
23 KiB
if not WeakAuras.IsLibsOK() then
|
|
return
|
|
end
|
|
---@type string
|
|
local AddonName = ...
|
|
---@class Private
|
|
local Private = select(2, ...)
|
|
|
|
---@class WeakAuras
|
|
local WeakAuras = WeakAuras
|
|
local L = WeakAuras.L
|
|
local prettyPrint = WeakAuras.prettyPrint
|
|
local LGF = LibStub("LibGetFrame-1.0")
|
|
|
|
local profileData = {}
|
|
profileData.systems = {}
|
|
profileData.auras = {}
|
|
|
|
local currentProfileState, ProfilingTimer
|
|
|
|
local table_to_string
|
|
table_to_string = function(tbl, depth)
|
|
if depth and depth >= 3 then
|
|
return "{ ... }"
|
|
end
|
|
local str
|
|
for k, v in pairs(tbl) do
|
|
if type(v) ~= "userdata" then
|
|
if type(v) == "table" then
|
|
v = table_to_string(v, (depth and depth + 1 or 1))
|
|
elseif type(v) == "function" then
|
|
v = "function"
|
|
elseif type(v) == "string" then
|
|
v = '"' .. v .. '"'
|
|
end
|
|
|
|
if type(k) == "string" then
|
|
k = '"' .. k .. '"'
|
|
end
|
|
|
|
str = (str and str .. "|cff999999,|r " or "|cff999999{|r ") .. "|cffffff99[" .. tostring(k) .. "]|r |cff999999=|r |cffffffff" .. tostring(v) .. "|r"
|
|
end
|
|
end
|
|
return (str or "{ ") .. " }"
|
|
end
|
|
|
|
WeakAurasProfilingReportMixin = {}
|
|
function WeakAurasProfilingReportMixin:OnShow()
|
|
if self.initialised then
|
|
return
|
|
end
|
|
self.initialised = true
|
|
|
|
ButtonFrameTemplate_HidePortrait(self)
|
|
self:SetTitle(L["WeakAuras Profiling Report"])
|
|
self:SetSize(500, 300)
|
|
end
|
|
|
|
function WeakAurasProfilingReportMixin:ClearText()
|
|
self.ScrollBox.messageFrame:SetText("")
|
|
end
|
|
|
|
function WeakAurasProfilingReportMixin:AddText(v)
|
|
if not v then
|
|
return
|
|
end
|
|
--- @type string?
|
|
local m = self.ScrollBox.messageFrame:GetText()
|
|
if m ~= "" then
|
|
m = m .. "|n"
|
|
end
|
|
if type(v) == "table" then
|
|
v = table_to_string(v)
|
|
end
|
|
self.ScrollBox.messageFrame.originalText = m .. v
|
|
self.ScrollBox.messageFrame:SetText(self.ScrollBox.messageFrame.originalText)
|
|
end
|
|
|
|
local function StartProfiling(map, id)
|
|
if not map[id] then
|
|
map[id] = {}
|
|
map[id].count = 1
|
|
map[id].start = debugprofilestop()
|
|
map[id].elapsed = 0
|
|
map[id].spike = 0
|
|
return
|
|
end
|
|
|
|
if map[id].count == 0 then
|
|
map[id].count = 1
|
|
map[id].start = debugprofilestop()
|
|
else
|
|
map[id].count = map[id].count + 1
|
|
end
|
|
end
|
|
|
|
local function StopProfiling(map, id)
|
|
map[id].count = map[id].count - 1
|
|
if map[id].count == 0 then
|
|
local elapsed = debugprofilestop() - map[id].start
|
|
map[id].elapsed = map[id].elapsed + elapsed
|
|
if elapsed > map[id].spike then
|
|
map[id].spike = elapsed
|
|
end
|
|
end
|
|
end
|
|
|
|
local function StartProfileSystem(system)
|
|
StartProfiling(profileData.systems, "wa")
|
|
StartProfiling(profileData.systems, system)
|
|
end
|
|
|
|
local function StartProfileAura(id)
|
|
StartProfiling(profileData.auras, id)
|
|
end
|
|
|
|
local function StopProfileSystem(system)
|
|
StopProfiling(profileData.systems, "wa")
|
|
StopProfiling(profileData.systems, system)
|
|
end
|
|
|
|
local function StopProfileAura(id)
|
|
StopProfiling(profileData.auras, id)
|
|
end
|
|
|
|
local function StartProfileUID(uid)
|
|
StartProfiling(profileData.auras, Private.UIDtoID(uid))
|
|
end
|
|
|
|
local function StopProfileUID(uid)
|
|
StopProfiling(profileData.auras, Private.UIDtoID(uid))
|
|
end
|
|
|
|
function Private.ProfileRenameAura(oldid, id)
|
|
profileData.auras[id] = profileData.auras[id]
|
|
profileData.auras[oldid] = nil
|
|
end
|
|
|
|
local RegisterProfile = function(startType)
|
|
if startType == "boss" then
|
|
startType = "encounter"
|
|
end
|
|
local delayedStart
|
|
if startType == "encounter" then
|
|
WeakAurasProfilingFrame:UnregisterAllEvents()
|
|
prettyPrint(L["Your next encounter will automatically be profiled."])
|
|
WeakAurasProfilingFrame:RegisterEvent("ENCOUNTER_START")
|
|
WeakAurasProfilingFrame:RegisterEvent("ENCOUNTER_END")
|
|
currentProfileState = startType
|
|
delayedStart = true
|
|
elseif startType == "combat" then
|
|
WeakAurasProfilingFrame:UnregisterAllEvents()
|
|
prettyPrint(L["Your next instance of combat will automatically be profiled."])
|
|
WeakAurasProfilingFrame:RegisterEvent("PLAYER_REGEN_DISABLED")
|
|
WeakAurasProfilingFrame:RegisterEvent("PLAYER_REGEN_ENABLED")
|
|
currentProfileState = startType
|
|
delayedStart = true
|
|
elseif startType == "autostart" then
|
|
prettyPrint(L["Profiling automatically started."])
|
|
currentProfileState = "profiling"
|
|
elseif startType and startType:match("%d") then
|
|
WeakAurasProfilingFrame:UnregisterAllEvents()
|
|
local time = startType + 0
|
|
prettyPrint(L["Profiling started. It will end automatically in %d seconds"]:format(time))
|
|
ProfilingTimer = WeakAuras.timer:ScheduleTimer(WeakAuras.StopProfile, time)
|
|
currentProfileState = "profiling"
|
|
else
|
|
WeakAurasProfilingFrame:UnregisterAllEvents()
|
|
prettyPrint(L["Profiling started."])
|
|
currentProfileState = "profiling"
|
|
end
|
|
WeakAurasProfilingFrame:UpdateButtons()
|
|
return delayedStart
|
|
end
|
|
|
|
---@diagnostic disable-next-line: duplicate-set-field
|
|
function WeakAuras.StartProfile(startType)
|
|
if currentProfileState == "profiling" then
|
|
prettyPrint(L["Profiling already started."])
|
|
return
|
|
end
|
|
|
|
if RegisterProfile(startType) then
|
|
-- Scheduled for later
|
|
return
|
|
end
|
|
|
|
profileData.systems = {}
|
|
profileData.auras = {}
|
|
profileData.systems.time = {}
|
|
profileData.systems.time.start = debugprofilestop()
|
|
profileData.systems.time.elapsed = nil
|
|
profileData.systems.time.count = 1
|
|
|
|
Private.StartProfileSystem = StartProfileSystem
|
|
Private.StartProfileAura = StartProfileAura
|
|
Private.StartProfileUID = StartProfileUID
|
|
Private.StopProfileSystem = StopProfileSystem
|
|
Private.StopProfileAura = StopProfileAura
|
|
Private.StopProfileUID = StopProfileUID
|
|
LGF.StartProfile()
|
|
end
|
|
|
|
local function doNothing() end
|
|
|
|
---@diagnostic disable-next-line: duplicate-set-field
|
|
function WeakAuras.StopProfile()
|
|
if currentProfileState ~= "profiling" then
|
|
prettyPrint(L["Profiling not running."])
|
|
return
|
|
end
|
|
|
|
prettyPrint(L["Profiling stopped."])
|
|
|
|
profileData.systems.time.elapsed = debugprofilestop() - profileData.systems.time.start
|
|
profileData.systems.time.count = 0
|
|
|
|
Private.StartProfileSystem = doNothing
|
|
Private.StartProfileAura = doNothing
|
|
Private.StartProfileUID = doNothing
|
|
Private.StopProfileSystem = doNothing
|
|
Private.StopProfileAura = doNothing
|
|
Private.StopProfileUID = doNothing
|
|
LGF.StopProfile()
|
|
|
|
currentProfileState = nil
|
|
if WeakAurasProfilingFrame then
|
|
WeakAurasProfilingFrame:UnregisterAllEvents()
|
|
WeakAurasProfilingFrame:UpdateButtons()
|
|
end
|
|
|
|
if ProfilingTimer then
|
|
WeakAuras.timer:CancelTimer(ProfilingTimer)
|
|
ProfilingTimer = nil
|
|
end
|
|
end
|
|
|
|
function WeakAuras.ToggleProfile()
|
|
if not profileData.systems.time or profileData.systems.time.count ~= 1 then
|
|
WeakAuras.StartProfile()
|
|
else
|
|
WeakAuras.StopProfile()
|
|
end
|
|
end
|
|
|
|
local function CancelScheduledProfile()
|
|
prettyPrint(L["Your scheduled automatic profile has been cancelled."])
|
|
currentProfileState = nil
|
|
WeakAurasProfilingFrame:UnregisterAllEvents()
|
|
WeakAurasProfilingFrame:UpdateButtons()
|
|
end
|
|
|
|
WeakAuras.CancelScheduledProfile = CancelScheduledProfile
|
|
|
|
local function AutoStartStopProfiling(frame, event)
|
|
if event == "ENCOUNTER_START" or event == "PLAYER_REGEN_DISABLED" then
|
|
WeakAuras.StartProfile("autostart")
|
|
elseif event == "ENCOUNTER_END" or event == "PLAYER_REGEN_ENABLED" then
|
|
WeakAuras.StopProfile()
|
|
end
|
|
end
|
|
|
|
local function ColoredSpike(spike)
|
|
local r, g, b
|
|
if spike < 2 then
|
|
r, g, b = WeakAuras.GetHSVTransition(spike / 2, 0, 1, 0, 1, 1, 1, 0, 1)
|
|
elseif spike < 2.5 then
|
|
r, g, b = WeakAuras.GetHSVTransition((spike - 2) * 2, 1, 1, 0, 1, 1, 0.65, 0, 1)
|
|
elseif spike < 3 then
|
|
r, g, b = WeakAuras.GetHSVTransition((spike - 2.5) * 2, 1, 0.65, 0, 1, 1, 0, 0, 1)
|
|
else
|
|
r, g, b = 1, 0, 0
|
|
end
|
|
return ("|cff%02x%02x%02x%.2fms|r"):format(r * 255, g * 255, b * 255, spike)
|
|
end
|
|
|
|
local function PrintOneProfile(popup, name, map, total)
|
|
if map.count ~= 0 then
|
|
popup:AddText(name .. " ERROR: count is not zero:" .. " " .. map.count)
|
|
end
|
|
|
|
local percent = ""
|
|
if total then
|
|
percent = (", %.2f%%"):format(100 * map.elapsed / total)
|
|
end
|
|
|
|
local spikeInfo = ""
|
|
if map.spike then
|
|
spikeInfo = ColoredSpike(map.spike)
|
|
end
|
|
|
|
popup:AddText(("%s |cff999999%.2fms%s (%s)|r"):format(name, map.elapsed, percent, spikeInfo))
|
|
end
|
|
|
|
local function SortProfileMap(map, sortField)
|
|
local result = {}
|
|
for k in pairs(map) do
|
|
tinsert(result, k)
|
|
end
|
|
|
|
sort(result, function(a, b)
|
|
if sortField then
|
|
local x, y = map[a][sortField], map[b][sortField]
|
|
if x and y then
|
|
return x > y
|
|
end
|
|
end
|
|
|
|
return map[a].elapsed > map[b].elapsed
|
|
end)
|
|
|
|
return result
|
|
end
|
|
|
|
local function TotalProfileTime(map)
|
|
local total = 0
|
|
for k, v in pairs(map) do
|
|
if k ~= "time" and k ~= "wa" then
|
|
total = total + v.elapsed
|
|
end
|
|
end
|
|
return total
|
|
end
|
|
|
|
local function unitEventToMultiUnit(event)
|
|
local count
|
|
event, count = event:gsub("nameplate%d+$", "nameplate")
|
|
if count == 1 then
|
|
return event
|
|
end
|
|
event, count = event:gsub("boss%d$", "boss")
|
|
if count == 1 then
|
|
return event
|
|
end
|
|
event, count = event:gsub("arena%d$", "arena")
|
|
if count == 1 then
|
|
return event
|
|
end
|
|
event, count = event:gsub("raid%d+$", "group")
|
|
if count == 1 then
|
|
return event
|
|
end
|
|
event, count = event:gsub("raidpet%d+$", "group")
|
|
if count == 1 then
|
|
return event
|
|
end
|
|
event, count = event:gsub("party%d$", "party")
|
|
if count == 1 then
|
|
return event
|
|
end
|
|
event, count = event:gsub("partypet%d$", "party")
|
|
return event
|
|
end
|
|
|
|
---@diagnostic disable-next-line: duplicate-set-field
|
|
function WeakAuras.PrintProfile()
|
|
local popup = WeakAurasProfilingReport
|
|
if not profileData.systems.time then
|
|
prettyPrint(L["No Profiling information saved."])
|
|
return
|
|
end
|
|
|
|
if profileData.systems.time.count == 1 then
|
|
prettyPrint(L["Profiling still running, stop before trying to print."])
|
|
return
|
|
end
|
|
|
|
popup:ClearAllPoints()
|
|
if WeakAurasProfilingFrame and WeakAurasProfilingFrame:IsShown() then
|
|
popup:SetParent(WeakAurasProfilingFrame)
|
|
popup:SetPoint("TOPLEFT", WeakAurasProfilingFrame, "TOPRIGHT", 5, 0)
|
|
else
|
|
popup:SetParent(UIParent)
|
|
if WeakAurasSaved.ProfilingWindow then
|
|
popup:SetPoint("TOPLEFT", UIParent, "TOPLEFT", WeakAurasSaved.ProfilingWindow.xOffset or 0, WeakAurasSaved.ProfilingWindow.yOffset or 0)
|
|
else
|
|
popup:SetPoint("CENTER")
|
|
end
|
|
end
|
|
|
|
popup:ClearText()
|
|
|
|
PrintOneProfile(popup, "|cff9900ffTotal time:|r", profileData.systems.time)
|
|
PrintOneProfile(popup, "|cff9900ffTime inside WA:|r", profileData.systems.wa)
|
|
popup:AddText(string.format("|cff9900ffTime spent inside WA:|r %.2f%%", 100 * profileData.systems.wa.elapsed / profileData.systems.time.elapsed))
|
|
|
|
popup:AddText("")
|
|
popup:AddText("Note: Not every aspect of each aura can be tracked.")
|
|
popup:AddText("You can ask on our discord https://discord.gg/weakauras for help interpreting this output.")
|
|
|
|
popup:AddText("")
|
|
popup:AddText("|cff9900ffAuras:|r")
|
|
local total = TotalProfileTime(profileData.auras)
|
|
popup:AddText("Total time attributed to auras: ", floor(total) .. "ms")
|
|
for _, k in ipairs(SortProfileMap(profileData.auras), "spike") do
|
|
PrintOneProfile(popup, k, profileData.auras[k], total)
|
|
end
|
|
|
|
popup:AddText("")
|
|
popup:AddText("|cff9900ffSystems:|r")
|
|
|
|
-- make a new table for system data with multiUnits grouped
|
|
local systemRegrouped = {}
|
|
for k, v in pairs(profileData.systems) do
|
|
local event = unitEventToMultiUnit(k)
|
|
if systemRegrouped[event] == nil then
|
|
systemRegrouped[event] = CopyTable(v)
|
|
else
|
|
if v.elapsed then
|
|
systemRegrouped[event].elapsed = (systemRegrouped[event].elapsed or 0) + v.elapsed
|
|
end
|
|
if v.spike then
|
|
systemRegrouped[event].spike = (systemRegrouped[event].spike or 0) + v.spike
|
|
end
|
|
end
|
|
end
|
|
|
|
for i, k in ipairs(SortProfileMap(systemRegrouped)) do
|
|
if k ~= "time" and k ~= "wa" then
|
|
PrintOneProfile(popup, k, systemRegrouped[k], profileData.systems.wa.elapsed)
|
|
end
|
|
end
|
|
|
|
popup:AddText("")
|
|
popup:AddText("|cff9900ffLibGetFrame:|r")
|
|
for id, map in pairs(LGF.GetProfileData()) do
|
|
PrintOneProfile(popup, id, map)
|
|
end
|
|
|
|
popup:Show()
|
|
end
|
|
|
|
WeakAurasProfilingLineMixin = {
|
|
spikeTooltip = L["Maximum time used on a single frame"],
|
|
timeTooltip = L["Cumulated time used during profiling"],
|
|
}
|
|
|
|
function WeakAurasProfilingLineMixin:Init(e)
|
|
-- button.pct:SetText(pct)
|
|
self.progressBar.name:SetText(e.name)
|
|
self.time:SetText(("%.2fms"):format(e.time))
|
|
self.spike:SetText(ColoredSpike(e.spike))
|
|
self.progressBar:SetValue(e.pct)
|
|
end
|
|
|
|
local COLUMN_INFO = {
|
|
{
|
|
title = L["Name"],
|
|
width = 300,
|
|
attribute = "name",
|
|
},
|
|
{
|
|
title = L["Time"],
|
|
width = 80,
|
|
attribute = "time",
|
|
},
|
|
{
|
|
title = L["Spike"],
|
|
width = 80,
|
|
attribute = "spike",
|
|
},
|
|
}
|
|
|
|
local function ApplyAlternateState(frame, alternate)
|
|
if alternate then
|
|
frame.progressBar:SetStatusBarColor(0.7, 0.7, 0.7, 0.7)
|
|
else
|
|
frame.progressBar:SetStatusBarColor(0.5, 0.5, 0.5, 0.7)
|
|
end
|
|
end
|
|
|
|
local modes = {
|
|
L["Auras"],
|
|
L["Systems"],
|
|
}
|
|
WeakAurasProfilingMixin = {}
|
|
|
|
function WeakAurasProfilingMixin:OnShow()
|
|
if self.initialised then
|
|
return
|
|
end
|
|
self.initialised = true
|
|
|
|
ButtonFrameTemplate_HidePortrait(self)
|
|
self:SetTitle(L["WeakAuras Profiling"])
|
|
self:SetSize(500, 300)
|
|
self.mode = 1
|
|
UIDropDownMenu_SetText(self.buttons.modeDropDown, modes[1])
|
|
|
|
self.buttons.report:SetText(L["Report Summary"])
|
|
self.buttons.report.tooltip = L["A detailed overview of your auras and WeakAuras systems\nCopy the whole text to Weakaura's Discord if you need assistance."]
|
|
|
|
local minimizeButton = CreateFrame("Button", nil, self, "MaximizeMinimizeButtonFrameTemplate")
|
|
minimizeButton:SetPoint("RIGHT", self.CloseButton, "LEFT")
|
|
minimizeButton:SetOnMaximizedCallback(function()
|
|
self.minimized = false
|
|
self.buttons:Show()
|
|
self.ColumnDisplay:Show()
|
|
self.ScrollBox:Show()
|
|
self.ScrollBar:Show()
|
|
self.stats:Show()
|
|
self:ClearAllPoints()
|
|
self:SetPoint("TOPRIGHT", UIParent, "BOTTOMLEFT", self.right, self.top)
|
|
self:SetHeight(self.prevHeight)
|
|
end)
|
|
minimizeButton:SetOnMinimizedCallback(function()
|
|
self.minimized = true
|
|
self.buttons:Hide()
|
|
self.ColumnDisplay:Hide()
|
|
self.ScrollBox:Hide()
|
|
self.ScrollBar:Hide()
|
|
self.stats:Hide()
|
|
self.right, self.top = self:GetRight(), self:GetTop()
|
|
self:ClearAllPoints()
|
|
self:SetPoint("TOPRIGHT", UIParent, "BOTTOMLEFT", self.right, self.top)
|
|
self.prevHeight = self:GetHeight()
|
|
self:SetHeight(60)
|
|
end)
|
|
|
|
self.ColumnDisplay:LayoutColumns(COLUMN_INFO)
|
|
|
|
local view = CreateScrollBoxListLinearView()
|
|
view:SetElementInitializer("WeakAurasProfilingLineTemplate", function(frame, elementData)
|
|
frame:Init(elementData)
|
|
end)
|
|
ScrollUtil.InitScrollBoxListWithScrollBar(self.ScrollBox, self.ScrollBar, view)
|
|
ScrollUtil.RegisterAlternateRowBehavior(self.ScrollBox, ApplyAlternateState)
|
|
|
|
self.sortField = "time"
|
|
self.bars = CreateDataProvider()
|
|
self:SortByColumnIndex(2)
|
|
self.ScrollBox:SetDataProvider(self.bars)
|
|
|
|
self:InitDropDown()
|
|
self:InitModeDropDown()
|
|
self:SetScript("OnEvent", AutoStartStopProfiling)
|
|
|
|
self:SetScript("OnUpdate", function()
|
|
if profileData.systems.time and profileData.systems.time.count > 0 then
|
|
self:RefreshBars()
|
|
end
|
|
end)
|
|
self:UpdateButtons()
|
|
end
|
|
|
|
function WeakAurasProfilingResultButton_OnClick(self)
|
|
WeakAuras.PrintProfile()
|
|
end
|
|
|
|
local function nextEncounterButton_OnClick(self)
|
|
if currentProfileState ~= "encounter" then
|
|
WeakAuras.StartProfile("encounter")
|
|
end
|
|
local parent = self:GetParent()
|
|
local profilingFrame = parent.dropdown.Button:GetParent():GetParent():GetParent()
|
|
profilingFrame:ResetBars()
|
|
profilingFrame:UpdateButtons()
|
|
end
|
|
|
|
local function nextCombatButton_OnClick(self)
|
|
if currentProfileState ~= "combat" then
|
|
WeakAuras.StartProfile("combat")
|
|
end
|
|
local parent = self:GetParent()
|
|
local profilingFrame = parent.dropdown.Button:GetParent():GetParent():GetParent()
|
|
profilingFrame:ResetBars()
|
|
profilingFrame:UpdateButtons()
|
|
end
|
|
|
|
local function startNowButton_OnClick(self)
|
|
WeakAuras.StartProfile()
|
|
local parent = self:GetParent()
|
|
local profilingFrame = parent.dropdown.Button:GetParent():GetParent():GetParent()
|
|
profilingFrame:ResetBars()
|
|
profilingFrame:UpdateButtons()
|
|
end
|
|
|
|
function WeakAurasProfilingStopButton_OnClick(self)
|
|
if currentProfileState == "profiling" then
|
|
WeakAuras.StopProfile()
|
|
else
|
|
CancelScheduledProfile()
|
|
end
|
|
self:GetParent():GetParent():UpdateButtons()
|
|
end
|
|
|
|
function WeakAurasProfilingMixin:InitDropDown()
|
|
local function Initializer(dropDown, level)
|
|
local entries = {
|
|
{
|
|
text = L["Start Now"],
|
|
func = startNowButton_OnClick,
|
|
},
|
|
{
|
|
text = L["Next Encounter"],
|
|
func = nextEncounterButton_OnClick,
|
|
},
|
|
{
|
|
text = L["Next Combat"],
|
|
func = nextCombatButton_OnClick,
|
|
},
|
|
}
|
|
for _, entry in ipairs(entries) do
|
|
local info = UIDropDownMenu_CreateInfo()
|
|
info.notCheckable = true
|
|
info.text = entry.text
|
|
info.func = entry.func
|
|
UIDropDownMenu_AddButton(info)
|
|
end
|
|
end
|
|
|
|
local dropDown = self.buttons.startDropDown
|
|
local dropDownButton = self.buttons.start
|
|
UIDropDownMenu_SetInitializeFunction(dropDown, Initializer)
|
|
UIDropDownMenu_SetDisplayMode(dropDown, "MENU")
|
|
|
|
dropDownButton.Text:SetText(L["Start Profiling"])
|
|
dropDownButton:SetScript("OnMouseDown", function(o, button)
|
|
UIMenuButtonStretchMixin.OnMouseDown(dropDownButton, button)
|
|
ToggleDropDownMenu(1, nil, dropDown, dropDownButton, 130, 20)
|
|
end)
|
|
end
|
|
|
|
local function selectMode(self, mode)
|
|
local parent = self:GetParent()
|
|
local profilingFrame = parent.dropdown.Button:GetParent():GetParent():GetParent()
|
|
profilingFrame.mode = mode
|
|
UIDropDownMenu_SetText(profilingFrame.buttons.modeDropDown, modes[mode])
|
|
profilingFrame:ResetBars()
|
|
profilingFrame:RefreshBars(nil, true)
|
|
end
|
|
|
|
function WeakAurasProfilingMixin:InitModeDropDown()
|
|
local function Initializer(dropDown, level)
|
|
for i = 1, 2 do
|
|
local info = UIDropDownMenu_CreateInfo()
|
|
info.text = modes[i]
|
|
info.func = selectMode
|
|
info.checked = i == self.mode
|
|
info.arg1 = i
|
|
UIDropDownMenu_AddButton(info)
|
|
end
|
|
end
|
|
|
|
local dropDown = self.buttons.modeDropDown
|
|
UIDropDownMenu_SetWidth(dropDown, 120)
|
|
UIDropDownMenu_JustifyText(dropDown, "LEFT")
|
|
UIDropDownMenu_Initialize(dropDown, Initializer)
|
|
end
|
|
|
|
|
|
local lastRefresh
|
|
function WeakAurasProfilingMixin:RefreshBars(_, force)
|
|
if force or (not lastRefresh or lastRefresh < GetTime() - 1) then
|
|
lastRefresh = GetTime()
|
|
else
|
|
return
|
|
end
|
|
|
|
if not profileData.systems.time then
|
|
return
|
|
end
|
|
|
|
local data
|
|
if self.mode == 1 then -- auras
|
|
data = profileData.auras
|
|
elseif self.mode == 2 then -- systems
|
|
data = {}
|
|
for k, v in pairs(profileData.systems) do
|
|
if k ~= "time" and k ~= "wa" then
|
|
local event = unitEventToMultiUnit(k)
|
|
if data[event] == nil then
|
|
data[event] = CopyTable(v)
|
|
else
|
|
if v.elapsed then
|
|
data[event].elapsed = (data[event].elapsed or 0) + v.elapsed
|
|
end
|
|
if v.spike then
|
|
data[event].spike = (data[event].spike or 0) + v.spike
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
local total = TotalProfileTime(data)
|
|
for _, name in ipairs(SortProfileMap(data)) do
|
|
if name ~= "time" and name ~= "wa" then
|
|
local elapsed = data[name].elapsed
|
|
local pct = 100 * elapsed / total
|
|
local spike = data[name].spike
|
|
self:UpdateBar(name, elapsed, pct, spike)
|
|
end
|
|
end
|
|
|
|
self.bars:Sort()
|
|
if profileData.systems.wa then
|
|
local timespent = profileData.systems.time.elapsed or (debugprofilestop() - profileData.systems.time.start)
|
|
self.stats:SetText(
|
|
("|cFFFFFFFFTime in WA: %.2fs / %ds (%.1f%%)"):format(profileData.systems.wa.elapsed / 1000, timespent / 1000, 100 * profileData.systems.wa.elapsed / timespent)
|
|
)
|
|
end
|
|
end
|
|
|
|
function WeakAurasProfilingMixin:ResetBars()
|
|
self.bars:Flush()
|
|
end
|
|
|
|
function WeakAurasProfilingMixin:UpdateBar(name, time, pct, spike)
|
|
local elementData = self.bars:FindElementDataByPredicate(function(elementData)
|
|
return elementData.name == name
|
|
end)
|
|
if elementData then
|
|
elementData.time = time
|
|
elementData.pct = pct
|
|
elementData.spike = spike
|
|
local button = WeakAurasProfilingFrame.ScrollBox:FindFrame(elementData)
|
|
if button then
|
|
button.time:SetText(("%.2fms"):format(time))
|
|
button.spike:SetText(ColoredSpike(spike))
|
|
button.progressBar:SetValue(pct)
|
|
end
|
|
else
|
|
self.bars:Insert({ name = name, time = time, pct = pct, spike = spike })
|
|
end
|
|
end
|
|
|
|
function WeakAurasProfilingMixin:SortByColumnIndex(index)
|
|
local previousField = self.sortField
|
|
self.sortField = COLUMN_INFO[index].attribute
|
|
if previousField == self.sortField then
|
|
self.sortDirection = not self.sortDirection
|
|
else
|
|
self.sortDirection = true
|
|
end
|
|
self.bars:SetSortComparator(function(lhs, rhs)
|
|
local field = self.sortField
|
|
local lhsF, rhsF = lhs[field] or 0, rhs[field] or 0
|
|
if type(lhsF) == "string" then
|
|
lhsF = lhsF:lower()
|
|
end
|
|
if type(rhsF) == "string" then
|
|
rhsF = rhsF:lower()
|
|
end
|
|
if lhsF == rhsF then
|
|
return lhs.name < rhs.name
|
|
end
|
|
if self.sortDirection then
|
|
return lhsF > rhsF
|
|
else
|
|
return lhsF < rhsF
|
|
end
|
|
end)
|
|
end
|
|
|
|
function WeakAurasProfilingMixin:UpdateButtons()
|
|
local b = self.buttons
|
|
if currentProfileState == "combat" or currentProfileState == "encounter" then
|
|
b.stop:SetText(L["Cancel"])
|
|
b.stop:Show()
|
|
b.start:Hide()
|
|
elseif currentProfileState == "profiling" then
|
|
b.stop:SetText(L["Stop"])
|
|
b.stop:Show()
|
|
b.start:Hide()
|
|
else
|
|
b.start:Show()
|
|
b.stop:Hide()
|
|
if profileData.systems.time then
|
|
b.report:Show()
|
|
end
|
|
end
|
|
end
|
|
|
|
function WeakAurasProfilingMixin:Start()
|
|
self:Show()
|
|
end
|
|
|
|
function WeakAurasProfilingMixin:Stop()
|
|
WeakAuras.StopProfile()
|
|
self:UpdateButtons()
|
|
self:ResetBars()
|
|
end
|
|
|
|
function WeakAurasProfilingMixin:Toggle()
|
|
if self:IsShown() then
|
|
self:Stop()
|
|
else
|
|
self:Start()
|
|
end
|
|
end
|
|
|
|
function WeakAurasProfilingColumnDisplay_OnClick(self, columnIndex)
|
|
self:GetParent():SortByColumnIndex(columnIndex)
|
|
end
|
|
|