Nenue@50: --- Devian - Devian.lua Nenue@32: -- @file-author@ Nenue@32: -- @project-revision@ @project-hash@ Nenue@32: -- @file-revision@ @file-hash@ Nenue@66: Nenue@91: --GLOBALS: Devian, DevianLoadMessage, DEVIAN_WORKSPACE, DEVIAN_PNAME, DEVIAN_PID Nenue@91: Nenue@91: DEVIAN_WORKSPACE = false Nenue@91: DEVIAN_PNAME = 'Dvn' Nenue@91: DEVIAN_PID = 0 Nenue@79: Nenue@66: local ADDON, D = ... Nenue@79: local MAJOR, MINOR = 'Devian-2.0', 'r@project-revision@' Nenue@79: local D = LibStub("AceAddon-3.0"):NewAddon(D, "Devian", "AceConsole-3.0", "AceEvent-3.0") Nenue@79: local L = D.L Nenue@79: Devian = D Nenue@72: local sub, GetTime, print, _G = string.sub, GetTime, print, _G Nenue@72: local format, setmetatable, getprinthandler, setprinthandler = string.format, setmetatable, getprinthandler, setprinthandler Nenue@79: local tinsert, tremove, rawset = tinsert, tremove, rawset Nenue@66: local currentProfile Nenue@66: local playerName = UnitName("player") Nenue@66: local playerRealm = playerName .. '-' .. GetRealmName() Nenue@66: local num_dock_tabs = 0 Nenue@93: local charStates ={} Nenue@79: Nenue@79: DevianLoadMessage = setmetatable({}, { Nenue@79: __call = function(t, msg) Nenue@79: rawset(t, #t+1, msg) Nenue@79: end, Nenue@79: __index = function(t) Nenue@79: return #t Nenue@79: end Nenue@79: }) Nenue@79: Nenue@66: --@debug@ Nenue@66: D.debugmode = true Nenue@66: --@end-debug@ Nenue@66: D.print = function(...) Nenue@66: if currentProfile and not currentProfile.workspace then Nenue@66: return Nenue@66: end Nenue@66: Nenue@66: if D.debugmode then Nenue@66: return print('Dvn', ...) Nenue@66: else Nenue@93: return nop Nenue@66: end Nenue@0: end Nenue@66: local print = D.print Nenue@66: Nenue@66: D.L = setmetatable({}, { Nenue@66: __index= function(t,k) Nenue@66: return k Nenue@66: end, Nenue@66: __call = function(t,k,...) Nenue@72: return format((t[k] or k) , ...) Nenue@66: end Nenue@66: }) Nenue@46: D:SetDefaultModuleState(false) Nenue@66: D.oldprint = getprinthandler() Nenue@66: if not _G.oldprint then _G.oldprint = D.oldprint end Nenue@66: Nenue@47: local pairs, tostring, tonumber, ipairs, type = pairs, tostring, tonumber, ipairs, type Nenue@66: local max, rand, format, print = max, math.random, string.format, print Nenue@47: local insert, wipe, concat = table.insert, table.wipe, table.concat Nenue@47: local select, unpack = select, unpack Nenue@47: local GetNumAddOns, GetAddOnInfo, GetAddOnEnableState, EnableAddOn = GetNumAddOns, GetAddOnInfo, GetAddOnEnableState, EnableAddOn Nenue@47: local UnitName, DisableAddOn = UnitName, DisableAddOn Nenue@66: Nenue@9: local db Nenue@13: local defaults = { Nenue@66: global = {{}, {}}, Nenue@66: default_channel = { Nenue@55: signature = 'Main', Nenue@55: x = 100, y = 800, Nenue@55: height = 500, width = 600, Nenue@66: enabled = true}, Nenue@66: current_profile = 1, Nenue@66: main_profile = 1, Nenue@66: last_profile = 1, Nenue@66: profilesName = {}, Nenue@66: profiles = { Nenue@45: }, Nenue@33: font = [[Interface\Addons\Devian\font\SourceCodePro-Regular.ttf]], -- font info Nenue@13: fontsize = 13, Nenue@13: fontoutline = 'NONE', Nenue@45: Nenue@45: headergrad = {'VERTICAL', 0, 0, 0, 1, Nenue@45: 1, 0.1, 0.1, 1}, -- header info Nenue@33: headerdrop = {1,1,1,1}, Nenue@45: headerblend = 'BLEND', Nenue@33: headeralpha = 1, Nenue@45: headerfontcolor = {1,1,1,1}, Nenue@45: Nenue@45: backdrop = {1,1,1,1}, -- background frame info Nenue@56: backgrad = {'VERTICAL', 0, 0, 0, .75, 0,0,0, .65}, Nenue@55: backblend = 'BLEND', Nenue@45: backalpha = 1, Nenue@45: backborder = {.5,.5,.5,1}, Nenue@45: backheader = {.25,.25,.25,1}, Nenue@45: Nenue@45: frontdrop = {1,1,1,1}, -- foreground frame info Nenue@56: frontgrad = {'VERTICAL', 0, 0, 0, 1, 0,0,0, 0.95}, Nenue@55: frontblend = 'BLEND', Nenue@28: frontalpha = 1, Nenue@45: frontborder = {.07,.47,1,1}, Nenue@45: frontheader = {1,1,1,1}, Nenue@33: tagcolor = {}, -- tag color repository Nenue@36: workspace = 2, -- current profile Nenue@47: last_workspace = 2, -- default workspace to alternate with when just "/dvn" is issued Nenue@47: Nenue@47: dock_onshow_fade_time = 2.5, Nenue@47: dock_onshow_fade_from = 1, Nenue@47: dock_onshow_fade_to = 0.2, Nenue@47: Nenue@47: dock_alpha_on = 1, Nenue@47: dock_alpha_off = 0.2, Nenue@47: dock_fade_in = 0.15, Nenue@47: dock_fade_out = 0.45, Nenue@47: dock_button_alpha_on = 1, Nenue@47: dock_button_alpha_off = 0.2, Nenue@50: dock_button_fade_in = 0.075, Nenue@55: dock_button_fade_out = 0.075, Nenue@47: Nenue@55: movement_fade = true, Nenue@55: movement_fade_time = 0.15, Nenue@60: movement_fade_from = 1, Nenue@60: movement_fade_to = 0, Nenue@60: movement_translation_x = 25, Nenue@60: movement_translation_y = 25, Nenue@13: } Nenue@9: Nenue@66: D.console = {} Nenue@66: D.max_channel = 0 Nenue@0: Nenue@67: D.InWorkspace = function () Nenue@67: return db.profiles[db.current_profile].workspace Nenue@67: end Nenue@67: Nenue@86: local profileTemplate = { Nenue@86: name = function(id, name) return name end, Nenue@86: workspace = function(id, name) return (id ~= 1) end, Nenue@86: current_channel = 1, Nenue@86: default_channel = 1, Nenue@86: num_channels = 1, Nenue@86: max_channel = 1, -- the highest created channel id Nenue@86: enabled = true, -- allow enabled consoles to appear Nenue@86: channels = { Nenue@86: { Nenue@86: index = 1, Nenue@86: signature = 'Main', Nenue@86: x = 100, y = 800, Nenue@86: height = 500, width = 600, Nenue@86: enabled = true Nenue@86: } Nenue@86: }, Nenue@86: loadouts = {}, Nenue@86: global = {}, Nenue@86: tags = {}, Nenue@86: char = { Nenue@86: [playerRealm] = {} Nenue@86: }, Nenue@86: unlisted = {} Nenue@86: } Nenue@86: Nenue@86: --- Applies complex template tables Nenue@86: -- If he value is a function, then it will invoke f(...) and use whatever gets returned Nenue@86: function D.DeepCopy(src, dest, ...) Nenue@86: Nenue@86: for k,v in pairs(src) do Nenue@86: if not dest[k] then Nenue@93: --oldprint('Rebuilding conf value', k) Nenue@86: if type(v) == 'table' then Nenue@86: dest[k] = {} Nenue@86: D.DeepCopy(v, dest[k], ...) Nenue@86: Nenue@86: else Nenue@86: if type(v) == 'function' then Nenue@86: v = v(...) Nenue@86: end Nenue@86: dest[k] = v Nenue@86: end Nenue@86: end Nenue@86: end Nenue@86: end Nenue@86: Nenue@66: D.Profile = function (id, name) Nenue@66: Nenue@66: if name and not id and db.profilesName[name] then Nenue@66: id = db.profilesName[name] Nenue@66: print('ID located by name, |cFF00FF00'..name..'|r is |cFFFFFF00'.. id..'|r') Nenue@66: end Nenue@66: Nenue@66: if not id or not db.profiles[id] then Nenue@66: if not id then Nenue@66: id = #db.profiles+1 Nenue@66: print('Generated profile ID: |cFFFFFF00'.. id .. '|r') Nenue@66: end Nenue@66: Nenue@66: if not name or db.profilesName[name] then Nenue@66: local newName = name or (id == 1 and 'Main' or 'Profile') Nenue@66: local prefix = newName Nenue@66: local i = 2 Nenue@66: while db.profilesName[newName] do Nenue@66: i = i + 1 Nenue@66: newName = prefix .. i Nenue@66: end Nenue@66: name = newName Nenue@66: print('Generated profile name: |cFF00FF00'..newName..'|r') Nenue@66: end Nenue@86: Nenue@86: Nenue@86: Nenue@66: print('Creating profile') Nenue@66: db.profilesName[name] = id Nenue@86: db.profiles[id] = {} Nenue@66: end Nenue@66: Nenue@86: Nenue@86: Nenue@66: D.currentProfile = db.profiles[id] Nenue@66: currentProfile = D.currentProfile Nenue@86: Nenue@86: D.DeepCopy(profileTemplate, currentProfile, id, name) Nenue@86: Nenue@86: Nenue@66: currentProfile.char[playerRealm] = currentProfile.char[playerRealm] or {} Nenue@66: if currentProfile.workspace then Nenue@79: DEVIAN_WORKSPACE = true Nenue@91: DEVIAN_PNAME = currentProfile.name Nenue@89: DEVIAN_PID = id Nenue@66: setprinthandler(D.Message) Nenue@66: else Nenue@79: DEVIAN_WORKSPACE = false Nenue@93: DEVIAN_PNAME = nil Nenue@93: print = nop Nenue@66: end Nenue@89: DEVIAN_PID =id Nenue@66: Nenue@66: D.unlisted = currentProfile.unlisted Nenue@66: D.channels = currentProfile.channels Nenue@66: D.tags = currentProfile.tags Nenue@66: D.channelinfo = currentProfile.channels Nenue@66: D.char = currentProfile.char[playerRealm] Nenue@66: D.global = currentProfile.global Nenue@66: D.num_channels = currentProfile.num_channels Nenue@66: D.enabled = currentProfile.enabled Nenue@66: D.sig = {} Nenue@66: D.sigID = {} Nenue@66: D.IDsig = {} Nenue@72: D.dock = _G.DevianDock Nenue@66: D.dock.buttons = D.dock.buttons or {} Nenue@66: Nenue@66: return id, name Nenue@66: end Nenue@66: Nenue@66: local targetGlobal, targetChar Nenue@86: D.Command = function (cmd) Nenue@66: local list_id, scan_func, reload Nenue@86: Nenue@14: local args = {} Nenue@86: if cmd then Nenue@86: local i, j = 0, 0 Nenue@86: repeat Nenue@86: i, j = cmd:find("%S+", j+1) Nenue@86: if i and j then Nenue@86: tinsert(args, cmd:sub(i, j)) Nenue@86: end Nenue@86: Nenue@86: until not(i or j) Nenue@14: end Nenue@14: local mode, tag, dest = unpack(args) Nenue@0: Nenue@86: Nenue@14: -- no args, toggle ui Nenue@86: if mode == 'rc' then Nenue@93: return D:ResetChannels(tag) Nenue@86: elseif mode == 'stack' then Nenue@14: return D:StackFrames() Nenue@14: elseif mode == 'grid' then Nenue@14: return D:DistributeFrames() Nenue@14: elseif mode == 'tag' then -- tagging Nenue@93: return D:Tag(tag, dest) Nenue@73: elseif mode == 'new' then Nenue@93: return D:New(tag) Nenue@93: elseif mode == 'dock' then Nenue@93: D.db.dockPoint = tag Nenue@93: return D:UpdateDock() Nenue@73: elseif mode == 'remove' then Nenue@93: return D:Remove(tag) Nenue@89: elseif mode ~= nil then Nenue@89: -- profile selector or save command Nenue@66: if mode == 'save' then Nenue@66: list_id = tonumber(tag) Nenue@89: else Nenue@89: list_id = tonumber(mode) Nenue@89: end Nenue@89: Nenue@89: if not list_id then Nenue@89: if db.profilesName[tostring(list_id)] then Nenue@89: list_id = db.profilesName[tostring(list_id)] Nenue@89: else Nenue@89: Nenue@89: D:Print(L('Unable to resolve profile ID/name', list_id, dest)) Nenue@89: return Nenue@66: end Nenue@89: end Nenue@89: Nenue@89: Nenue@89: if mode == 'save' then Nenue@66: D.Profile(list_id, dest) Nenue@66: scan_func = D.Save Nenue@89: Nenue@89: Nenue@89: local name = currentProfile.name Nenue@89: if dest then Nenue@89: dest = dest:gsub("$%s+", ''):gsub("%s+^", '') Nenue@89: if dest then Nenue@89: if name then Nenue@89: db.profilesName[name] = nil Nenue@89: end Nenue@89: db.profiles[list_id].name = dest Nenue@89: db.profilesName[dest] = list_id Nenue@92: Nenue@92: name = dest Nenue@89: end Nenue@89: end Nenue@89: Nenue@89: Nenue@89: D:Print("Profile |cFFFFFF00".. list_id .."|r:|cFF00FFFF".. name .."|r saved.") Nenue@66: else Nenue@32: Nenue@89: if db.profiles[list_id] then Nenue@89: D.LoadMessage ("Switched profiles.") Nenue@89: if list_id ~= db.main_profile then Nenue@89: db.last_profile = list_id Nenue@89: end Nenue@89: db.current_profile = list_id Nenue@89: scan_func = D.Load Nenue@89: else Nenue@89: return D:PrintHelp() Nenue@89: end Nenue@36: Nenue@0: end Nenue@32: elseif mode == nil then Nenue@66: list_id = (db.current_profile ~= db.main_profile) and db.main_profile or db.last_profile Nenue@77: D.LoadMessage ("Switched between main and recent profile ("..db.current_profile..' and '..list_id..')') Nenue@66: db.current_profile = list_id Nenue@66: scan_func = D.Load Nenue@32: else Nenue@89: Nenue@89: Nenue@32: return D:PrintHelp() Nenue@0: end Nenue@77: Nenue@77: if not db.profiles[list_id] then Nenue@77: db.profiles[list_id] = {global = {}, char = {} } Nenue@77: D.LoadMessage ("Starting profile #|cFF00FFFF".. list_id..'|r') Nenue@77: end Nenue@67: if not db.profiles[list_id].char[playerRealm] then Nenue@67: db.profiles[list_id].char[playerRealm] = {} Nenue@67: end Nenue@67: Nenue@66: targetGlobal = db.profiles[list_id].global Nenue@66: targetChar = db.profiles[list_id].char[playerRealm] Nenue@32: Nenue@67: Nenue@66: if scan_func then Nenue@93: wipe(charStates) Nenue@66: for id, name, enableState, globalState in D.Addons() do Nenue@66: scan_func(id, name, enableState, globalState) Nenue@0: end Nenue@0: end Nenue@0: Nenue@66: if scan_func == D.Load then Nenue@72: _G.ReloadUI() Nenue@93: if AddonList_Update then Nenue@93: AddonList_Update() Nenue@93: end Nenue@93: elseif (scan_func == D.Save) then Nenue@93: print('reckoning') Nenue@93: local updated = {} Nenue@93: for addon, newState in pairs(charStates) do Nenue@93: for character, addons in pairs(db.profiles[list_id].char) do Nenue@93: if addons[addon] then Nenue@93: print(addon, addons[addon], '::', newState) Nenue@93: if (addons[addon] ~= newState) then Nenue@93: addons[addon] = newState Nenue@93: updated[character] = (updated[character] or 0) + 1 Nenue@93: end Nenue@93: Nenue@93: end Nenue@93: Nenue@93: end Nenue@93: end Nenue@93: for character, numAddons in pairs(updated) do Nenue@93: print(character, numAddons, 'settings') Nenue@93: end Nenue@93: Nenue@66: end Nenue@93: Nenue@93: Nenue@66: D.Profile(db.current_profile) Nenue@66: end Nenue@66: Nenue@66: D.Addons = function() Nenue@66: local playername = UnitName("player") Nenue@66: return function(n, i) Nenue@66: if i >= n then Nenue@66: return nil Nenue@66: end Nenue@66: Nenue@66: i = i + 1 Nenue@66: local name = GetAddOnInfo(i) Nenue@66: local enableState, globalState = GetAddOnEnableState(playername, i), GetAddOnEnableState(nil, i) Nenue@66: return i, name, enableState, globalState Nenue@66: end, GetNumAddOns(), 0 Nenue@66: end Nenue@66: Nenue@66: D.Load = function(id, name, charState, globalState) Nenue@93: print('load', tostring(name), tostring(charState), tostring(globalState)) Nenue@93: if targetGlobal[name] == 2 then Nenue@93: EnableAddOn(id, true) Nenue@93: elseif targetChar[name] == 2 then Nenue@93: EnableAddOn(id, playerName) Nenue@93: elseif targetGlobal[name] == 0 then Nenue@93: DisableAddOn(id, true) Nenue@93: elseif targetChar[name] == 0 then Nenue@93: DisableAddOn(id, playerName) Nenue@93: end Nenue@93: Nenue@93: if not (targetChar[name] or targetGlobal[name]) then Nenue@66: tinsert(D.unlisted, name) Nenue@66: end Nenue@93: Nenue@66: end Nenue@93: Nenue@93: Nenue@66: D.Save = function(id, name, charState, globalState) Nenue@93: if (charState ~= 0) or (globalState ~= 0) then Nenue@93: print('save', id, name, playerRealm .. ': '.. charState, 'All: '.. globalState) Nenue@93: end Nenue@93: Nenue@66: targetGlobal[name] = globalState Nenue@66: targetChar[name] = charState Nenue@93: Nenue@93: -- if enabling/disabling globally Nenue@93: if globalState ~= 1 then Nenue@93: charStates[name] = globalState Nenue@93: end Nenue@66: end Nenue@57: Nenue@66: D.Tag = function(self, tag, dest) Nenue@66: local sig Nenue@66: if tag ~= nil and dest ~= nil then Nenue@66: --@debug@ Nenue@66: --print(tag, dest) Nenue@66: --@end-debug@ Nenue@66: Nenue@66: -- convert to ID Nenue@66: if tonumber(dest) == nil then Nenue@66: if D.sigID[dest] then Nenue@66: dest = currentProfile.channels[D.sigID[dest]].index Nenue@66: else Nenue@66: sig = dest Nenue@66: end Nenue@57: else Nenue@66: dest = tonumber(dest) Nenue@32: end Nenue@66: --@debug@ Nenue@66: --print('2 tag,dest,sig', tag, dest, sig)--@end-debug@ Nenue@66: Nenue@66: -- make a new channel? Nenue@66: local channel Nenue@66: if not currentProfile.channels[dest] then Nenue@66: dest = D.max_channel + 1 Nenue@66: D:Print(L('New channel created', sig and (dest..':'..sig) or dest )) Nenue@66: channel = D:SetChannel(sig or tag,dest) Nenue@66: else Nenue@66: channel = D.channels[dest] Nenue@66: end Nenue@66: --@debug@ Nenue@66: --print('3 tag,dest,channel.sig=',tag, dest, channel.signature)--@end-debug@ Nenue@66: Nenue@66: if not currentProfile.tags[tag] then -- no tag table? Nenue@66: currentProfile.tags[tag] = {} Nenue@66: end Nenue@66: Nenue@66: if currentProfile.tags[tag][dest] then -- is tag set? Nenue@66: currentProfile.tags[tag][dest] = nil Nenue@66: D:Print(L('Tag removed from channel', tag, currentProfile.channels[dest].index, currentProfile.channels[dest].signature)) Nenue@66: else Nenue@66: currentProfile.tags[tag][dest] = dest Nenue@66: D:Print(L('Tag added to channel', tag, currentProfile.channels[dest].index, currentProfile.channels[dest].signature)) Nenue@66: end Nenue@66: D:UpdateDock() Nenue@66: else Nenue@66: D:Print(L['Command tag help']) Nenue@0: end Nenue@0: end Nenue@0: Nenue@86: D.ResetChannels = function(self, profile) Nenue@86: currentProfile.current_channel = 1 Nenue@86: currentProfile.primary_channel = 1 Nenue@86: currentProfile.channels = {} Nenue@86: D.DeepCopy(profileTemplate.channels, currentProfile.channels) Nenue@86: currentProfile.tags = {} Nenue@86: D.LoadMessage('Profile reset.') Nenue@86: ReloadUI() Nenue@86: end Nenue@86: Nenue@73: D.New = function(self, tag) Nenue@73: if tag and not self.sigID[tag] then Nenue@73: local id = D.max_channel + 1 Nenue@73: D.SetChannel(tag, id) Nenue@73: end Nenue@73: end Nenue@0: Nenue@73: D.Remove = function(self, dest) Nenue@73: dest = D.sigID[dest] or tonumber(dest) Nenue@73: if D.console[dest] and D.channels[dest] then Nenue@73: for tag, tagDest in pairs(D.tags) do Nenue@73: for i = #tagDest, 0 do Nenue@73: -- work downward so we aren't skipping entries Nenue@73: if tagDest[i] == dest then Nenue@73: tremove(tagDest, i) Nenue@73: end Nenue@73: end Nenue@73: end Nenue@73: D.console[dest]:Hide() Nenue@73: D.channels[dest] = nil Nenue@73: tremove(D.console, dest) Nenue@93: D.dock.buttons[dest]:SetShown(false) Nenue@73: D:UpdateDock() Nenue@73: D:Print('Removed channel #'..dest) Nenue@73: end Nenue@73: end Nenue@13: Nenue@77: --- Queue up a message to appear after UI reload Nenue@77: function D.LoadMessage(msg) Nenue@77: Nenue@77: tinsert(_G.DevianLoadMessage, msg) Nenue@77: end Nenue@77: Nenue@18: --- Creates a Devian-style output. Nenue@18: -- The first argument describes the channel to output on, and the remaining arguments are concatenated in a manner similar to default print() Nenue@18: -- This becomes the print handler when development mode is active. The original print() function is assigned to oldprint(). Nenue@18: -- @param Tag, signature, or numeric index of the channel to output on. Defaults to primary channel. Nenue@18: -- @param ... Output contents. Nenue@72: Nenue@66: function D.Message(prefix, ...) Nenue@67: if not currentProfile.workspace then Nenue@23: return D.oldprint(prefix, ...) Nenue@23: end Nenue@57: prefix = tostring(prefix) Nenue@57: if prefix == nil then Nenue@55: prefix = 'nil*' Nenue@1: end Nenue@9: Nenue@18: local sendq = {} Nenue@30: local tag, id, tagged Nenue@13: local byName = true Nenue@18: if D.tags[prefix] then Nenue@18: for _, id in pairs(D.tags[prefix]) do Nenue@18: if D.console[id] then Nenue@18: sendq[id] = D.console[id] Nenue@30: tagged = true Nenue@18: end Nenue@18: end Nenue@18: end Nenue@18: Nenue@13: if D.sig[prefix] then Nenue@18: sendq[D.sig[prefix].index] = D.sig[prefix] Nenue@13: elseif D.console[prefix] then Nenue@18: sendq[D.console[prefix]] = D.console[prefix] Nenue@30: elseif not tagged then Nenue@18: sendq[D.primary_channel] = D.console[D.primary_channel] Nenue@13: end Nenue@18: Nenue@9: -- color me timbers Nenue@9: local pcolor Nenue@18: if (not db.tagcolor[prefix]) and byName then Nenue@86: -- numbers, use white Nenue@86: if prefix:match('^%d+%.%d+') then Nenue@73: pcolor = 'FFFFFF' Nenue@73: else Nenue@73: local c = { Nenue@73: rand(64,255), rand(64,255), rand(64,255) Nenue@73: } Nenue@73: if c[1] > 223 and c[2] > 223 and c[3] > 223 then Nenue@73: c[rand(1,3)] = rand(64,223) Nenue@73: end Nenue@73: db.tagcolor[prefix] = format('%02X%02X%02X', unpack(c)) Nenue@73: pcolor = db.tagcolor[prefix] Nenue@0: end Nenue@73: else Nenue@73: pcolor = db.tagcolor[prefix] Nenue@0: end Nenue@0: Nenue@55: local buffer = {} Nenue@0: for i = 1, select('#',...) do Nenue@0: local var = select(i, ...) Nenue@0: Nenue@0: if type(var) == 'table' then Nenue@20: if type(var.GetName) == 'function' then Nenue@72: var = '[table:'..tostring(var:GetName())..']' Nenue@20: else Nenue@32: var = '<'..tostring(var)..'>' Nenue@20: end Nenue@20: Nenue@0: elseif type(var) == 'boolean' then Nenue@75: var = var and 'true' or 'false' Nenue@0: elseif type(var) == 'function' then Nenue@72: var = '['..tostring(var)..']' Nenue@0: elseif type(var) == 'nil' then Nenue@75: var = 'nil' Nenue@60: else Nenue@60: var = tostring(var) Nenue@0: end Nenue@0: Nenue@47: insert(buffer, var) Nenue@0: end Nenue@47: local message = concat(buffer, ' ') Nenue@18: for id, channel in pairs(sendq) do Nenue@55: if channel.width < 250 then Nenue@72: prefix = sub(prefix, 0,2) Nenue@55: end Nenue@73: --currentProfile.last_channel = channel.index Nenue@58: channel.out:AddMessage('|cFF'.. pcolor..prefix ..'|r ' .. message, 0.8, 0.8, 0.8, nil, nil, prefix, GetTime()) Nenue@93: if not D.dock.usedButtons[id].newMessage then Nenue@93: D.dock.usedButtons[id].newMessage = true Nenue@93: D.dock.usedButtons[id].caption.pulse:Play() Nenue@93: D.dock.usedButtons[id]:Update() Nenue@58: end Nenue@18: end Nenue@47: wipe(buffer) Nenue@0: end Nenue@0: Nenue@14: Nenue@32: Nenue@14: Nenue@32: function D:PrintHelp() Nenue@32: D:Print("|cFFFFFF00/dvn|r", Nenue@32: "\n |cFFFFFF00|r - Loads a saved addon list. List 1 is treated as a gameplay profile and consoles will be disabled by default.") Nenue@47: D:Print("|cFFFFFF00/dvc|r [, ...]", "- Hides and show consoles. A list of channel keys can be passed to specify which ones get toggled.") Nenue@32: Nenue@32: D:Print("|cFFFFFF00/resetdvn|r", "- Resets all but profile data SavedVariables.") Nenue@32: D:Print("|cFFFFFF00/cleandvn|r", "- Fully resets SavedVariables, profiles and all.") Nenue@32: end Nenue@32: Nenue@66: local blocked = {profiles = true, debugmode = true} Nenue@66: D.SetDefaults = function() Nenue@72: local DevianDB = _G.DevianDB Nenue@66: for k,v in pairs(DevianDB) do Nenue@66: if not blocked[k] then Nenue@66: DevianDB[k] = nil Nenue@60: end Nenue@60: end Nenue@66: for k,v in pairs(defaults) do Nenue@66: if not blocked[k] then Nenue@66: DevianDB[k] = v Nenue@60: end Nenue@60: end Nenue@73: Nenue@77: D.LoadMessage "Non-user SavedVars have been reset." Nenue@72: _G.ReloadUI() Nenue@60: end Nenue@66: D.SetDefaultsAll = function () Nenue@72: _G.DevianDB = nil Nenue@77: D.LoadMessage "All SavedVars wiped." Nenue@72: _G.ReloadUI() Nenue@66: end Nenue@73: Nenue@73: D.UnsetColors = function() Nenue@73: db.tagcolor = {} Nenue@73: D:Print('Tag color cache cleared.') Nenue@73: end Nenue@45: Nenue@33: Nenue@89: function D.ConsoleCommand (cmd) Nenue@89: D:Console_Toggle(cmd) Nenue@89: end Nenue@87: Nenue@66: Nenue@66: function D:OnInitialize() Nenue@81: L = D.L Nenue@13: Nenue@33: -- pull defaults Nenue@9: if not _G.DevianDB then Nenue@13: _G.DevianDB = defaults Nenue@9: end Nenue@9: db = _G.DevianDB Nenue@47: self.db = db Nenue@0: Nenue@66: --- Nenue@77: if #_G.DevianLoadMessage >= 1 then Nenue@77: for i, msg in ipairs(_G.DevianLoadMessage) do Nenue@77: D:Print(msg) Nenue@77: end Nenue@77: Nenue@77: table.wipe(_G.DevianLoadMessage) Nenue@0: end Nenue@0: Nenue@66: Nenue@89: -- commands Nenue@89: local cmdlist = { Nenue@89: ['dvn'] = "Command", Nenue@89: ['devian'] = "Command", Nenue@89: ['dvc'] = "ConsoleCommand", Nenue@89: ['dvncolors'] = "UnsetColors", Nenue@89: ['cleandvn'] = "SetDefaultsAll", Nenue@89: ['resetdvn'] = "SetDefaults", Nenue@89: } Nenue@89: for cmd, func in pairs(cmdlist) do Nenue@89: local CMD = cmd:upper() Nenue@89: _G['SLASH_' .. CMD .. '1'] = "/"..cmd Nenue@89: Nenue@89: if type(func == 'string') then Nenue@93: --print('SLASH_' .. CMD .. '1','/'.. cmd, func) Nenue@89: SlashCmdList[CMD] = D[func] Nenue@89: else Nenue@93: --print('SLASH_' .. CMD .. '1','/'.. cmd, func) Nenue@89: SlashCmdList[CMD] = func Nenue@89: end Nenue@89: end Nenue@89: Nenue@66: --- initialize the current profile Nenue@66: local id, name = D.Profile(db.current_profile or 1) Nenue@66: D:Print('Using profile |cFFFFFF00'.. id ..'|r: |cFF00FF00'..currentProfile.name..'|r') Nenue@66: if currentProfile.workspace then Nenue@66: D:Print('Workspace: '.. (#currentProfile.channels) .. ' channels, ' .. #currentProfile.tags .. ' tags.') Nenue@86: if D.channels[currentProfile.default_channel] then Nenue@86: D:Print('Default channel: |cFFFFFF00'..currentProfile.default_channel..'|r: |cFF00FFFF'.. D.channels[currentProfile.default_channel].signature..'|r') Nenue@86: end Nenue@0: end Nenue@13: Nenue@86: Nenue@66: for i, cinfo in pairs(D.channels) do Nenue@14: i = tonumber(i) Nenue@66: if not D.primary_channel then Nenue@66: D.primary_channel = i Nenue@14: end Nenue@66: D:SetChannel(cinfo, i) Nenue@66: D.num_channels = D.num_channels + 1 Nenue@32: end Nenue@86: D.primary_channel = D.primary_channel or 1 Nenue@32: Nenue@66: D.max_channel = max(D.max_channel, currentProfile.max_channel) Nenue@66: if currentProfile.max_channel < D.max_channel then Nenue@66: for i = currentProfile.max_channel, D.max_channel do Nenue@66: D.console[i]:Hide() Nenue@47: end Nenue@36: end Nenue@36: Nenue@66: if currentProfile.workspace then Nenue@66: if D.console[currentProfile.current_channel] then Nenue@69: --print('bringing', D.console[currentProfile.current_channel].signature, 'to the front') Nenue@66: D.console[currentProfile.current_channel]:ToFront() Nenue@66: -- bring the current channel to the front Nenue@47: end Nenue@72: _G.DevianDock:Show() Nenue@66: D:UpdateDock() Nenue@36: end Nenue@66: end Nenue@89: