--[[-------------------------------------------------------------------- Copyright (C) 2012, 2013, 2014 Johnny C. Lam. See the file LICENSE.txt for copying permission. --]]---------------------------------------------------------------------- local OVALE, Ovale = ... local OvaleDebug = Ovale:NewModule("OvaleDebug", "AceTimer-3.0") Ovale.OvaleDebug = OvaleDebug --<private-static-properties> local AceConfig = LibStub("AceConfig-3.0") local AceConfigDialog = LibStub("AceConfigDialog-3.0") local L = Ovale.L local LibTextDump = LibStub("LibTextDump-1.0") local OvaleOptions = Ovale.OvaleOptions local format = string.format local gmatch = string.gmatch local gsub = string.gsub local next = next local pairs = pairs local strlen = string.len local tonumber = tonumber local tostring = tostring local type = type local API_GetSpellInfo = GetSpellInfo local API_GetTime = GetTime local DEFAULT_CHAT_FRAME = DEFAULT_CHAT_FRAME -- Flags used by debugging print functions. -- If "traced" flag is set, then the public "trace" property is toggled before the next frame refresh. local self_traced = false -- LibTextDump-1.0 object for output from Log() or Logf() methods. local self_traceLog = nil -- Maximum length of the trace log. local OVALE_TRACELOG_MAXLINES = 4096 -- 2^14 do local actions = { debug = { name = L["Debug"], type = "execute", func = function() local appName = OvaleDebug:GetName() AceConfigDialog:SetDefaultSize(appName, 800, 550) AceConfigDialog:Open(appName) end, }, } -- Insert actions into OvaleOptions. for k, v in pairs(actions) do OvaleOptions.options.args.actions.args[k] = v end -- Add a global data type for debug options. OvaleOptions.defaultDB.global = OvaleOptions.defaultDB.global or {} OvaleOptions.defaultDB.global.debug = {} OvaleOptions:RegisterOptions(OvaleDebug) end --</private-static-properties> --<public-static-properties> OvaleDebug.options = { name = OVALE .. " " .. L["Debug"], type = "group", args = { toggles = { name = L["Options"], type = "group", order = 10, args = {}, get = function(info) local value = Ovale.db.global.debug[info[#info]] return (value ~= nil) end, set = function(info, value) value = value or nil Ovale.db.global.debug[info[#info]] = value end, }, trace = { name = L["Trace"], type = "group", order = 20, args = { trace = { order = 10, type = "execute", name = L["Trace"], desc = L["Trace the next frame update."], func = function() self_traceLog:Clear() OvaleDebug.trace = true OvaleDebug:Log("=== Trace @%f", API_GetTime()) OvaleDebug:ScheduleTimer("DisplayTraceLog", 0.5) end, }, traceLog = { order = 20, type = "execute", name = L["Show Trace Log"], func = function() OvaleDebug:DisplayTraceLog() end, }, traceSpellId = { order = 30, type = "input", name = L["Trace spellcast"], desc = L["Names or spell IDs of spellcasts to watch, separated by semicolons."], get = function(info) local OvaleFuture = Ovale.OvaleFuture if OvaleFuture then local t = OvaleFuture.traceSpellList or {} local s = "" for k, v in pairs(t) do if type(v) == "boolean" then if strlen(s) == 0 then s = k else s = s .. "; " .. k end end end return s else return "" end end, set = function(info, value) local OvaleFuture = Ovale.OvaleFuture if OvaleFuture then local t = {} for s in gmatch(value, "[^;]+") do -- strip leading and trailing whitespace s = gsub(s, "^%s*", "") s = gsub(s, "%s*$", "") if strlen(s) > 0 then local v = tonumber(s) if v then s = API_GetSpellInfo(v) if s then t[v] = true t[s] = v end else t[s] = true end end end if next(t) then OvaleFuture.traceSpellList = t else OvaleFuture.traceSpellList = nil end end end, }, }, }, }, } -- If "bug" flag is set, then the next frame refresh is traced. OvaleDebug.bug = false -- Flag to activate tracing the function calls for the next frame refresh. OvaleDebug.trace = false --</public-static-properties> --<public-static-methods> function OvaleDebug:OnInitialize() local appName = self:GetName() AceConfig:RegisterOptionsTable(appName, self.options) AceConfigDialog:AddToBlizOptions(appName, L["Debug"], OVALE) end function OvaleDebug:OnEnable() self_traceLog = LibTextDump:New(OVALE .. " - " .. L["Trace Log"], 750, 500) end function OvaleDebug:ResetTrace() self.bug = false self.trace = false self_traced = false end function OvaleDebug:UpdateTrace() -- If trace flag is set here, then flag that we just traced one frame. if self.trace then self_traced = true end -- If there was a bug, then enable trace on the next frame. if self.bug then self.trace = true end -- Toggle trace flag so we don't endlessly trace successive frames. if self.trace and self_traced then self_traced = false self.trace = false end end function OvaleDebug:RegisterDebugging(addon) local name = addon:GetName() self.options.args.toggles.args[name] = { name = name, desc = format(L["Enable debugging messages for the %s module."], name), type = "toggle", } addon.Debug = self.Debug end --[[ Output the parameters as a string to DEFAULT_CHAT_FRAME. If the first parameter is a boolean or nil, then treat it as a request to insert a timestamp at the beginning of the line. --]] function OvaleDebug:Debug(addTimestamp, ...) local name = self:GetName() if Ovale.db.global.debug[name] then local s if (type(addTimestamp) == "boolean" or type(addTimestamp) == "nil") then if (...) then if addTimestamp then -- Add a yellow timestamp to the start. local now = API_GetTime() s = format("|cffffff00%f|r %s", now, Ovale:MakeString(...)) else s = Ovale:MakeString(...) end else s = tostring(addTimestamp) end else s = Ovale:MakeString(addTimestamp, ...) end -- Match output format from AceConsole-3.0 Print() method. DEFAULT_CHAT_FRAME:AddMessage(format("|cff33ff99%s|r: %s", name, s)) end end function OvaleDebug:Log(...) if self.trace then local N = self_traceLog:Lines() if N < OVALE_TRACELOG_MAXLINES - 1 then self_traceLog:AddLine(Ovale:MakeString(...)) elseif N == OVALE_TRACELOG_MAXLINES - 1 then self_traceLog:AddLine("WARNING: Maximum length of trace log has been reached.") end end end function OvaleDebug:DisplayTraceLog() if self_traceLog:Lines() == 0 then self_traceLog:AddLine("Trace log is empty.") end self_traceLog:Display() end do local NEW_DEBUG_NAMES = { action_bar = "OvaleActionBar", aura = "OvaleAura", combo_points = "OvaleComboPoints", compile = "OvaleCompile", damage_taken = "OvaleDamageTaken", enemy = "OvaleEnemies", guid = "OvaleGUID", missing_spells = false, paper_doll = "OvalePaperDoll", power = "OvalePower", snapshot = false, spellbook = "OvaleSpellBook", state = "OvaleState", steady_focus = "OvaleSteadyFocus", unknown_spells = false, } function OvaleDebug:UpgradeSavedVariables() local global = Ovale.db.global local profile = Ovale.db.profile -- All profile-specific debug options are removed. They are now in the global database. profile.debug = nil -- Debugging options have changed names. for old, new in pairs(NEW_DEBUG_NAMES) do if global.debug[old] and new then global.debug[new] = global.debug[old] end global.debug[old] = nil end -- If a debug option is toggled off, it is "stored" as nil, not "false". for k, v in pairs(global.debug) do if not v then global.debug[k] = nil end end end end --</public-static-methods>