diff --git a/WeakAuras/AuraEnvironment.lua b/WeakAuras/AuraEnvironment.lua index 20b4da4..c43cac9 100644 --- a/WeakAuras/AuraEnvironment.lua +++ b/WeakAuras/AuraEnvironment.lua @@ -276,6 +276,10 @@ function Private.ActivateAuraEnvironment(id, cloneId, state, states, onlyConfig) end end +local function DebugPrint(...) + Private.DebugLog.Print(current_uid, ...) +end + local function blocked(key) Private.AuraWarnings.UpdateWarning(current_uid, "SandboxForbidden", "error", string.format(L["Forbidden function or table: %s"], key)) @@ -392,6 +396,8 @@ local exec_env = setmetatable({}, return env_getglobal elseif k == "aura_env" then return current_aura_env + elseif k == "DebugPrint" then + return DebugPrint elseif blockedFunctions[k] then blocked(k) return function() end diff --git a/WeakAuras/AuraWarnings.lua b/WeakAuras/AuraWarnings.lua index e09ac86..fb5fa85 100644 --- a/WeakAuras/AuraWarnings.lua +++ b/WeakAuras/AuraWarnings.lua @@ -10,6 +10,7 @@ local printedWarnings = {} local function OnDelete(event, uid) warnings[uid] = nil + printedWarnings[uid] = nil end Private.callbacks:RegisterCallback("Delete", OnDelete) @@ -37,6 +38,9 @@ local function UpdateWarning(uid, key, severity, message, printOnConsole) else if warnings[uid][key] then warnings[uid][key] = nil + if printedWarnings[uid] then + printedWarnings[uid][key] = nil + end Private.callbacks:Fire("AuraWarningsUpdated", uid) end end @@ -50,7 +54,7 @@ local severityLevel = { } local icons = { - info = { path = [[Interface\friendsframe\informationicon]] }, + info = { path = [[Interface\FriendsFrame\InformationIcon]] }, sound = { path = "Interface\\AddOns\\WeakAuras\\Media\\Textures\\ChatFrame", texCoords = {0.757812, 0.871094, 0.0078125, 0.234375} }, warning = { path = "Interface\\AddOns\\WeakAuras\\Media\\Textures\\ServicesAtlas", texCoords = {0.000976562, 0.0419922, 0.961914, 0.998047} }, error = { path = "Interface\\AddOns\\WeakAuras\\Media\\Textures\\HelpIcon-Bug" }, @@ -75,9 +79,9 @@ local function AddMessages(result, messages, icon, mixedSeverity) local iconPath = icon.path local texCoords = icon.texCoords if texCoords then - result = result .. string.format("|T%s:12:12:0:0:64:64:%d:%d:%d:%d|t", iconPath, texCoords[1] * 64, texCoords[2] * 64, texCoords[3] * 64, texCoords[4] * 64) + result = result .. string.format("|T%s:12:12:0:0:64:64:%d:%d:%d:%d|t", iconPath, texCoords[1] * 64, texCoords[2] * 64, texCoords[3] * 64, texCoords[4] * 64) else - result = result .. string.format("|T%s:12:12:0:0:64:64:4:60:4:60|t", iconPath) + result = result .. string.format("|T%s:12:12:0:0:64:64:4:60:4:60|t", iconPath) end end result = result .. message diff --git a/WeakAuras/DebugLog.lua b/WeakAuras/DebugLog.lua new file mode 100644 index 0000000..813d1d7 --- /dev/null +++ b/WeakAuras/DebugLog.lua @@ -0,0 +1,114 @@ +if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end +local AddonName, Private = ... + +local WeakAuras = WeakAuras +local L = WeakAuras.L + +local debugLogs = {} +local enabled = {} + +Private.DebugLog = { + -- Print + -- Clear + -- SetEnabled + -- IsEnabled + -- GetLogs +} + +local function serialize(log, input) + if type(input) == "table" then + if log[#log] == "" then + log[#log] = L["Dumping table"] + else + tinsert(log, L["Dumping table"]) + end + -- Use dump to create a table dump, because that already handles depth limitation + -- and cycles and looks nice + -- But this requires temporarily setting DEFAULT_CHAT_FRAME + -- Nothing can go wrong with that. + local defaultChatFrame = _G.DEFAULT_CHAT_FRAME + _G.DEFAULT_CHAT_FRAME = log + DevTools_Dump(input) + _G.DEFAULT_CHAT_FRAME = defaultChatFrame + tinsert(log, "") + else + if log[#log] == "" then + log[#log] = tostring(input) + else + log[#log] = log[#log] .. " " .. tostring(input) + end + end +end + +function Private.DebugLog.Print(uid, text, ...) + if enabled[uid] then + local log = debugLogs[uid] + tinsert(log, "") + if select('#', ...) == 0 then + serialize(log, text) + else + serialize(log, text) + local texts = {...} + for i = 1, select('#', ...) do + local v = select(i, ...) + serialize(log, v) + end + end + + if #log > 1000 then + Private.AuraWarnings.UpdateWarning(uid, "Debug_Log", "warning", + L["Debug Log contains more than 1000 entries"], + true) + end + end +end + +local function AddMessage(self, msg) + tinsert(self, msg) +end + +function Private.DebugLog.Clear(uid) + if enabled[uid] then + debugLogs[uid] = { + AddMessage = AddMessage + } + -- Dance to clear a potential console message from the AuraWarnings + Private.AuraWarnings.UpdateWarning(uid, "Debug_Log", "info") + Private.AuraWarnings.UpdateWarning(uid, "Debug_Log", "info", L["Debug Logging enabled"]) + end +end + +function Private.DebugLog.SetEnabled(uid, enable) + if enabled[uid] == enable then + return + end + enabled[uid] = enable + if enable then + debugLogs[uid] = { + AddMessage = AddMessage + } + Private.AuraWarnings.UpdateWarning(uid, "Debug_Log", "info", L["Debug Logging enabled"]) + else + debugLogs[uid] = nil + Private.AuraWarnings.UpdateWarning(uid, "Debug_Log", "info") + end +end + +function Private.DebugLog.IsEnabled(uid) + return enabled[uid] +end + +function Private.DebugLog.GetLogs(uid) + if debugLogs[uid] then + return table.concat(debugLogs[uid], "\n") + end +end + +local function OnDelete(_, uid) + debugLogs[uid] = nil + enabled[uid] = nil +end + +Private.callbacks:RegisterCallback("Delete", OnDelete) + + diff --git a/WeakAuras/WeakAuras.lua b/WeakAuras/WeakAuras.lua index a4d16b6..c778430 100644 --- a/WeakAuras/WeakAuras.lua +++ b/WeakAuras/WeakAuras.lua @@ -1570,6 +1570,10 @@ function Private.LoadDisplays(toLoad, ...) triggerState[id].show = false; triggerState[id].activeTrigger = nil; triggerState[id].activatedConditions = {}; + if Private.DebugLog.IsEnabled(uid) then + WeakAuras.prettyPrint(L["Debug Logging enabled for '%s'"]:format(id)) + Private.DebugLog.Print(uid, L["Aura loaded"]) + end end for _, triggerSystem in pairs(triggerSystems) do triggerSystem.LoadDisplays(toLoad, ...); @@ -2554,6 +2558,8 @@ local function pAdd(data, simpleChange) end Private.UpdatedTriggerState(id) else + Private.DebugLog.SetEnabled(data.uid, data.information.debugLog) + if (data.controlledChildren) then Private.ClearAuraEnvironment(id); for parent in Private.TraverseParents(data) do diff --git a/WeakAuras/WeakAuras.toc b/WeakAuras/WeakAuras.toc index cb98cff..61e6760 100644 --- a/WeakAuras/WeakAuras.toc +++ b/WeakAuras/WeakAuras.toc @@ -44,8 +44,11 @@ Conditions.lua BuffTrigger.lua BuffTrigger2.lua GenericTrigger.lua + +# Helper Systems AuraWarnings.lua AuraEnvironment.lua +DebugLog.lua # Region support RegionTypes\RegionPrototype.lua diff --git a/WeakAurasOptions/InformationOptions.lua b/WeakAurasOptions/InformationOptions.lua index 7f0a462..e8a7e6b 100644 --- a/WeakAurasOptions/InformationOptions.lua +++ b/WeakAurasOptions/InformationOptions.lua @@ -148,7 +148,7 @@ function OptionsPrivate.GetInformationOptions(data) end end - -- compatibility Options + -- compatibility Options args.compabilityTitle = { type = "header", name = L["Compatibility Options"], @@ -245,6 +245,94 @@ function OptionsPrivate.GetInformationOptions(data) end end + -- Debug Log + args.debugLogTitle = { + type = "header", + name = L["Enable Debug Log"], + width = WeakAuras.doubleWidth, + order = order, + } + order = order + 1 + args.debugLogDesc = { + type = "description", + name = L["This enables the collection of debug logs. This requires custom coded auras that use DebugPrints."], + width = WeakAuras.doubleWidth, + order = order, + } + order = order + 1 + local sameDebugLog = true + local commonDebugLog + local debugLogDesc = "" + for child in OptionsPrivate.Private.TraverseLeafsOrAura(data) do + local effectiveDebugLog = child.information.debugLog and true or false + debugLogDesc = debugLogDesc .. "|cFFE0E000"..child.id..": |r".. (effectiveDebugLog and "true" or "false") .. "\n" + if commonDebugLog == nil then + commonDebugLog = effectiveDebugLog + elseif effectiveDebugLog ~= commonDebugLog then + sameDebugLog = false + end + end + args.debugLogToggle = { + type = "toggle", + name = sameDebugLog and L["Enable Debug Logging"] or "|cFF4080FF" .. L["Enable Debug Logging"], + desc = not sameDebugLog and debugLogDesc or nil, + width = WeakAuras.doubleWidth, + order = order, + get = function() + return sameDebugLog and commonDebugLog + end, + set = function(info, v) + for child in OptionsPrivate.Private.TraverseLeafsOrAura(data) do + child.information.debugLog = v + WeakAuras.Add(child) + OptionsPrivate.ClearOptions(child.id) + end + WeakAuras.ClearAndUpdateOptions(data.id) + end + } + order = order + 1 + if not sameDebugLog or commonDebugLog then + args.debugLogShow = { + type = "execute", + name = L["Show Debug Logs"], + width = WeakAuras.normalWidth, + order = order, + func = function() + local fullMessage = L["WeakAuras %s on WoW %s"]:format(WeakAuras.versionString, WeakAuras.BuildInfo) .. "\n\n" + local haveLogs = false + for child in OptionsPrivate.Private.TraverseLeafsOrAura(data) do + local auraLog = OptionsPrivate.Private.DebugLog.GetLogs(child.uid) + if auraLog then + haveLogs = true + fullMessage = fullMessage .. L["Aura: '%s'"]:format(child.id) + local version = child.semver or child.version + if (version) then + fullMessage = fullMessage .. "\n" .. L["Version: %s"]:format(version) + end + fullMessage = fullMessage .. "\n" .. L["Debug Log:"] .. "\n" .. auraLog .. "\n\n" + end + end + if haveLogs then + OptionsPrivate.OpenDebugLog(fullMessage) + else + OptionsPrivate.OpenDebugLog(L["No Logs saved."]) + end + end + } + order = order + 1 + args.debugLogClear = { + type = "execute", + name = L["Clear Debug Logs"], + width = WeakAuras.normalWidth, + order = order, + func = function() + for child in OptionsPrivate.Private.TraverseLeafsOrAura(data) do + OptionsPrivate.Private.DebugLog.Clear(child.uid) + end + end + } + order = order + 1 + end return options end diff --git a/WeakAurasOptions/OptionsFrames/DebugLogFrame.lua b/WeakAurasOptions/OptionsFrames/DebugLogFrame.lua new file mode 100644 index 0000000..836f057 --- /dev/null +++ b/WeakAurasOptions/OptionsFrames/DebugLogFrame.lua @@ -0,0 +1,71 @@ +if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end +local AddonName, OptionsPrivate = ... + +-- WoW APIs +local CreateFrame = CreateFrame + +local AceGUI = LibStub("AceGUI-3.0") + +local WeakAuras = WeakAuras +local L = WeakAuras.L + +local debugLog + +local function ConstructDebugLog(frame) + local group = AceGUI:Create("WeakAurasInlineGroup"); + group.frame:SetParent(frame); + group.frame:SetPoint("TOPLEFT", frame, "TOPLEFT", 17, -63); + group.frame:SetPoint("BOTTOMRIGHT", frame, "BOTTOMRIGHT", -17, 46); + group.frame:Hide(); + group:SetLayout("flow"); + + local copyLabel = AceGUI:Create("Label") + copyLabel:SetFontObject(GameFontNormal) + copyLabel:SetFullWidth(true) + copyLabel:SetText(L["Press Ctrl+C to copy"]) + group:AddChild(copyLabel) + + local input = AceGUI:Create("MultiLineEditBox"); + input:DisableButton(true) + --input.frame:SetClipsChildren(true); + input.editBox:SetScript("OnEscapePressed", function() group:Close(); end); + input.editBox:SetScript("OnMouseUp", function() input.editBox:HighlightText(); end); + input:SetFullWidth(true) + input:SetFullHeight(true) + group:AddChild(input); + + local close = CreateFrame("Button", nil, group.frame, "UIPanelButtonTemplate"); + close:SetScript("OnClick", function() group:Close() end); + close:SetPoint("BOTTOMRIGHT", -20, -24) + close:SetFrameLevel(close:GetFrameLevel() + 1) + close:SetHeight(20); + close:SetWidth(100); + close:SetText(L["Close"]) + + function group.Open(self, text) + frame.window = "debuglog"; + frame:UpdateFrameVisible() + input.editBox:SetScript("OnTextChanged", function() input:SetText(text); input.editBox:HighlightText(); end); + input.editBox:SetScript("OnMouseUp", function() input.editBox:HighlightText(); end); + input:SetLabel(""); + input.button:Hide(); + input:SetText(text); + input.editBox:HighlightText(); + input:SetFocus() + + group:DoLayout() + end + + function group.Close(self) + input:ClearFocus(); + frame.window = "default"; + frame:UpdateFrameVisible() + end + + return group +end + +function OptionsPrivate.DebugLog(frame) + debugLog = debugLog or ConstructDebugLog(frame) + return debugLog +end diff --git a/WeakAurasOptions/OptionsFrames/OptionsFrame.lua b/WeakAurasOptions/OptionsFrames/OptionsFrame.lua index 9e7f8d9..f614d20 100644 --- a/WeakAurasOptions/OptionsFrames/OptionsFrame.lua +++ b/WeakAurasOptions/OptionsFrames/OptionsFrame.lua @@ -212,6 +212,7 @@ function OptionsPrivate.CreateFrame() self.update.frame:Hide() self.texteditor.frame:Hide() self.codereview.frame:Hide() + self.debugLog.frame:Hide() if self.newView then self.newView.frame:Hide() end @@ -292,6 +293,12 @@ function OptionsPrivate.CreateFrame() else self.update.frame:Hide() end + if self.window == "debuglog" then + OptionsPrivate.SetTitle(L["Debug Log"]) + self.debugLog.frame:Show() + else + self.debugLog.frame:Hide() + end if self.window == "default" then if self.loadProgessVisible then self.loadProgress:Show() @@ -486,6 +493,7 @@ function OptionsPrivate.CreateFrame() frame.texteditor = OptionsPrivate.TextEditor(frame) frame.codereview = OptionsPrivate.CodeReview(frame) frame.update = OptionsPrivate.UpdateFrame(frame) + frame.debugLog = OptionsPrivate.DebugLog(frame) frame.moversizer, frame.mover = OptionsPrivate.MoverSizer(frame) diff --git a/WeakAurasOptions/WeakAurasOptions.lua b/WeakAurasOptions/WeakAurasOptions.lua index 6a597f4..eb401a4 100644 --- a/WeakAurasOptions/WeakAurasOptions.lua +++ b/WeakAurasOptions/WeakAurasOptions.lua @@ -892,6 +892,10 @@ function OptionsPrivate.ImportFromString() frame.importexport:Open("import"); end +function OptionsPrivate.OpenDebugLog(text) + frame.debugLog:Open(text) +end + function OptionsPrivate.OpenUpdate(data, children, target, sender) return frame.update:Open(data, children, target, sender) end diff --git a/WeakAurasOptions/WeakAurasOptions.toc b/WeakAurasOptions/WeakAurasOptions.toc index 0357c7a..922f7ca 100644 --- a/WeakAurasOptions/WeakAurasOptions.toc +++ b/WeakAurasOptions/WeakAurasOptions.toc @@ -65,6 +65,7 @@ OptionsFrames\ModelPicker.lua OptionsFrames\TextEditor.lua OptionsFrames\TexturePicker.lua OptionsFrames\Update.lua +OptionsFrames\DebugLogFrame.lua # Misc frames OptionsFrames\MoverSizer.lua