annotate Devian.lua @ 110:930922e1ec5b v8.0.1-20181807-1

cleaning up XML warnings
author Nenue
date Wed, 18 Jul 2018 15:02:19 -0400
parents 7a36f5a92f0a
children
rev   line source
Nenue@50 1 --- Devian - Devian.lua
Nenue@32 2 -- @file-author@
Nenue@32 3 -- @project-revision@ @project-hash@
Nenue@32 4 -- @file-revision@ @file-hash@
Nenue@66 5
Nenue@91 6 --GLOBALS: Devian, DevianLoadMessage, DEVIAN_WORKSPACE, DEVIAN_PNAME, DEVIAN_PID
Nenue@91 7
Nenue@100 8 SLASH_RL1 = "/rl"
Nenue@100 9 SlashCmdList.RL = function() ReloadUI() end
Nenue@91 10 DEVIAN_WORKSPACE = false
Nenue@91 11 DEVIAN_PNAME = 'Dvn'
Nenue@91 12 DEVIAN_PID = 0
Nenue@79 13
Nenue@66 14 local ADDON, D = ...
Nenue@79 15 local MAJOR, MINOR = 'Devian-2.0', 'r@project-revision@'
Nenue@98 16 local D_INITIALIZED
Nenue@98 17 local next = next
Nenue@72 18 local sub, GetTime, print, _G = string.sub, GetTime, print, _G
Nenue@72 19 local format, setmetatable, getprinthandler, setprinthandler = string.format, setmetatable, getprinthandler, setprinthandler
Nenue@79 20 local tinsert, tremove, rawset = tinsert, tremove, rawset
Nenue@66 21 local currentProfile
Nenue@66 22 local playerName = UnitName("player")
Nenue@66 23 local playerRealm = playerName .. '-' .. GetRealmName()
Nenue@66 24 local num_dock_tabs = 0
Nenue@93 25 local charStates ={}
Nenue@79 26
Nenue@100 27 local channels_report = {}
Nenue@98 28 local registeredTags = {}
Nenue@98 29
Nenue@98 30
Nenue@98 31 DevianCore = {}
Nenue@98 32
Nenue@98 33 function DevianCore:OnLoad ()
Nenue@98 34 self:RegisterEvent('ADDON_LOADED')
Nenue@98 35 self:RegisterEvent('PLAYER_LOGIN')
Nenue@107 36
Nenue@98 37 self:SetShown(true)
Nenue@98 38 end
Nenue@98 39
Nenue@98 40 function DevianCore:OnEvent(event, arg)
Nenue@98 41 if event == 'ADDON_LOADED' or event == 'PLAYER_LOGIN' then
Nenue@98 42 --print(event, arg, DevianDB)
Nenue@98 43 if (arg == 'Devian') and not D_INITIALIZED then
Nenue@98 44 D_INITIALIZED = true
Nenue@98 45 self:Initialize()
Nenue@98 46 self:UnregisterAllEvents()
Nenue@98 47 end
Nenue@98 48 end
Nenue@98 49 end
Nenue@98 50
Nenue@79 51 DevianLoadMessage = setmetatable({}, {
Nenue@79 52 __call = function(t, msg)
Nenue@79 53 rawset(t, #t+1, msg)
Nenue@79 54 end,
Nenue@79 55 __index = function(t)
Nenue@79 56 return #t
Nenue@79 57 end
Nenue@79 58 })
Nenue@79 59
Nenue@66 60 --@debug@
Nenue@66 61 D.debugmode = true
Nenue@66 62 --@end-debug@
Nenue@66 63 D.print = function(...)
Nenue@66 64 if currentProfile and not currentProfile.workspace then
Nenue@98 65 return nop
Nenue@66 66 end
Nenue@66 67
Nenue@66 68 if D.debugmode then
Nenue@66 69 return print('Dvn', ...)
Nenue@66 70 else
Nenue@93 71 return nop
Nenue@66 72 end
Nenue@0 73 end
Nenue@66 74 local print = D.print
Nenue@66 75
Nenue@66 76 D.L = setmetatable({}, {
Nenue@66 77 __index= function(t,k)
Nenue@98 78 return tostring(k)
Nenue@66 79 end,
Nenue@66 80 __call = function(t,k,...)
Nenue@98 81 return format((t[k]) , ...)
Nenue@66 82 end
Nenue@66 83 })
Nenue@66 84 D.oldprint = getprinthandler()
Nenue@66 85 if not _G.oldprint then _G.oldprint = D.oldprint end
Nenue@66 86
Nenue@47 87 local pairs, tostring, tonumber, ipairs, type = pairs, tostring, tonumber, ipairs, type
Nenue@66 88 local max, rand, format, print = max, math.random, string.format, print
Nenue@47 89 local insert, wipe, concat = table.insert, table.wipe, table.concat
Nenue@47 90 local select, unpack = select, unpack
Nenue@47 91 local GetNumAddOns, GetAddOnInfo, GetAddOnEnableState, EnableAddOn = GetNumAddOns, GetAddOnInfo, GetAddOnEnableState, EnableAddOn
Nenue@47 92 local UnitName, DisableAddOn = UnitName, DisableAddOn
Nenue@66 93
Nenue@98 94 local db, L
Nenue@13 95 local defaults = {
Nenue@66 96 global = {{}, {}},
Nenue@66 97 default_channel = {
Nenue@55 98 signature = 'Main',
Nenue@98 99 x = 100, y = -200,
Nenue@55 100 height = 500, width = 600,
Nenue@66 101 enabled = true},
Nenue@66 102 current_profile = 1,
Nenue@66 103 main_profile = 1,
Nenue@66 104 last_profile = 1,
Nenue@66 105 profilesName = {},
Nenue@66 106 profiles = {
Nenue@45 107 },
Nenue@33 108 font = [[Interface\Addons\Devian\font\SourceCodePro-Regular.ttf]], -- font info
Nenue@13 109 fontsize = 13,
Nenue@13 110 fontoutline = 'NONE',
Nenue@45 111
Nenue@45 112 headergrad = {'VERTICAL', 0, 0, 0, 1,
Nenue@45 113 1, 0.1, 0.1, 1}, -- header info
Nenue@33 114 headerdrop = {1,1,1,1},
Nenue@45 115 headerblend = 'BLEND',
Nenue@33 116 headeralpha = 1,
Nenue@45 117 headerfontcolor = {1,1,1,1},
Nenue@45 118
Nenue@45 119 backdrop = {1,1,1,1}, -- background frame info
Nenue@56 120 backgrad = {'VERTICAL', 0, 0, 0, .75, 0,0,0, .65},
Nenue@55 121 backblend = 'BLEND',
Nenue@45 122 backalpha = 1,
Nenue@45 123 backborder = {.5,.5,.5,1},
Nenue@45 124 backheader = {.25,.25,.25,1},
Nenue@45 125
Nenue@45 126 frontdrop = {1,1,1,1}, -- foreground frame info
Nenue@56 127 frontgrad = {'VERTICAL', 0, 0, 0, 1, 0,0,0, 0.95},
Nenue@55 128 frontblend = 'BLEND',
Nenue@28 129 frontalpha = 1,
Nenue@45 130 frontborder = {.07,.47,1,1},
Nenue@45 131 frontheader = {1,1,1,1},
Nenue@33 132 tagcolor = {}, -- tag color repository
Nenue@36 133 workspace = 2, -- current profile
Nenue@47 134 last_workspace = 2, -- default workspace to alternate with when just "/dvn" is issued
Nenue@47 135
Nenue@47 136 dock_onshow_fade_time = 2.5,
Nenue@47 137 dock_onshow_fade_from = 1,
Nenue@47 138 dock_onshow_fade_to = 0.2,
Nenue@47 139
Nenue@47 140 dock_alpha_on = 1,
Nenue@47 141 dock_alpha_off = 0.2,
Nenue@47 142 dock_fade_in = 0.15,
Nenue@47 143 dock_fade_out = 0.45,
Nenue@47 144 dock_button_alpha_on = 1,
Nenue@47 145 dock_button_alpha_off = 0.2,
Nenue@50 146 dock_button_fade_in = 0.075,
Nenue@55 147 dock_button_fade_out = 0.075,
Nenue@47 148
Nenue@55 149 movement_fade = true,
Nenue@55 150 movement_fade_time = 0.15,
Nenue@60 151 movement_fade_from = 1,
Nenue@60 152 movement_fade_to = 0,
Nenue@60 153 movement_translation_x = 25,
Nenue@60 154 movement_translation_y = 25,
Nenue@13 155 }
Nenue@9 156
Nenue@66 157 D.console = {}
Nenue@66 158 D.max_channel = 0
Nenue@0 159
Nenue@67 160 D.InWorkspace = function ()
Nenue@67 161 return db.profiles[db.current_profile].workspace
Nenue@67 162 end
Nenue@67 163
Nenue@86 164 local profileTemplate = {
Nenue@86 165 name = function(id, name) return name end,
Nenue@86 166 workspace = function(id, name) return (id ~= 1) end,
Nenue@86 167 current_channel = 1,
Nenue@86 168 default_channel = 1,
Nenue@86 169 num_channels = 1,
Nenue@86 170 max_channel = 1, -- the highest created channel id
Nenue@86 171 enabled = true, -- allow enabled consoles to appear
Nenue@86 172 channels = {
Nenue@86 173 {
Nenue@86 174 index = 1,
Nenue@86 175 signature = 'Main',
Nenue@98 176 x = 100, y = -200,
Nenue@86 177 height = 500, width = 600,
Nenue@86 178 enabled = true
Nenue@86 179 }
Nenue@86 180 },
Nenue@86 181 loadouts = {},
Nenue@86 182 global = {},
Nenue@86 183 tags = {},
Nenue@86 184 char = {
Nenue@86 185 [playerRealm] = {}
Nenue@86 186 },
Nenue@86 187 unlisted = {}
Nenue@86 188 }
Nenue@86 189
Nenue@86 190 --- Applies complex template tables
Nenue@86 191 -- If he value is a function, then it will invoke f(...) and use whatever gets returned
Nenue@86 192 function D.DeepCopy(src, dest, ...)
Nenue@86 193
Nenue@86 194 for k,v in pairs(src) do
Nenue@86 195 if not dest[k] then
Nenue@93 196 --oldprint('Rebuilding conf value', k)
Nenue@86 197 if type(v) == 'table' then
Nenue@86 198 dest[k] = {}
Nenue@86 199 D.DeepCopy(v, dest[k], ...)
Nenue@86 200
Nenue@86 201 else
Nenue@86 202 if type(v) == 'function' then
Nenue@86 203 v = v(...)
Nenue@86 204 end
Nenue@86 205 dest[k] = v
Nenue@86 206 end
Nenue@86 207 end
Nenue@86 208 end
Nenue@86 209 end
Nenue@86 210
Nenue@98 211 D.FixProfile = function(forced)
Nenue@98 212
Nenue@98 213 local numChannels = 0
Nenue@98 214 local minChannel = 400
Nenue@98 215 local sortedChannels = {}
Nenue@98 216 local sortedTags = {}
Nenue@98 217 local maxChannel = 0
Nenue@98 218 for k,v in pairs(currentProfile.channels) do
Nenue@98 219 numChannels = numChannels + 1
Nenue@98 220 maxChannel = max(tonumber(k), maxChannel)
Nenue@98 221 minChannel = min(tonumber(k), minChannel)
Nenue@98 222 tinsert(sortedChannels, v)
Nenue@98 223 end
Nenue@98 224 if (maxChannel > numChannels) or forced then
Nenue@98 225 oldprint('fixing channels data')
Nenue@98 226 table.sort(sortedChannels, function(a,b)
Nenue@98 227 return (b.index > a.index)
Nenue@98 228 end)
Nenue@98 229 for i, info in ipairs(sortedChannels) do
Nenue@99 230
Nenue@99 231 info.tags = info.tags or {}
Nenue@98 232 for tag, tagSet in pairs(currentProfile.tags) do
Nenue@98 233 for _, index in pairs(tagSet) do
Nenue@98 234 if index == info.index then
Nenue@98 235 sortedTags[tag] = sortedTags[tag] or {}
Nenue@98 236 sortedTags[tag][i] = i
Nenue@99 237 tinsert(info.tags, tag)
Nenue@98 238 end
Nenue@98 239 end
Nenue@98 240 end
Nenue@99 241 print('Set tags:', table.concat(info.tags, ', '))
Nenue@98 242
Nenue@98 243 info.index = i
Nenue@98 244 end
Nenue@98 245 currentProfile.channels = sortedChannels
Nenue@98 246 currentProfile.tags = sortedTags
Nenue@98 247 else
Nenue@98 248 minChannel = 2
Nenue@98 249 end
Nenue@98 250 currentProfile.lastUpdateFix = MINOR
Nenue@98 251 end
Nenue@98 252
Nenue@66 253 D.Profile = function (id, name)
Nenue@66 254
Nenue@66 255 if name and not id and db.profilesName[name] then
Nenue@66 256 id = db.profilesName[name]
Nenue@66 257 print('ID located by name, |cFF00FF00'..name..'|r is |cFFFFFF00'.. id..'|r')
Nenue@66 258 end
Nenue@66 259
Nenue@66 260 if not id or not db.profiles[id] then
Nenue@66 261 if not id then
Nenue@66 262 id = #db.profiles+1
Nenue@66 263 print('Generated profile ID: |cFFFFFF00'.. id .. '|r')
Nenue@66 264 end
Nenue@66 265
Nenue@66 266 if not name or db.profilesName[name] then
Nenue@66 267 local newName = name or (id == 1 and 'Main' or 'Profile')
Nenue@66 268 local prefix = newName
Nenue@66 269 local i = 2
Nenue@66 270 while db.profilesName[newName] do
Nenue@66 271 i = i + 1
Nenue@66 272 newName = prefix .. i
Nenue@66 273 end
Nenue@66 274 name = newName
Nenue@66 275 print('Generated profile name: |cFF00FF00'..newName..'|r')
Nenue@66 276 end
Nenue@86 277
Nenue@86 278
Nenue@86 279
Nenue@66 280 print('Creating profile')
Nenue@66 281 db.profilesName[name] = id
Nenue@86 282 db.profiles[id] = {}
Nenue@66 283 end
Nenue@66 284
Nenue@86 285
Nenue@86 286
Nenue@66 287 D.currentProfile = db.profiles[id]
Nenue@66 288 currentProfile = D.currentProfile
Nenue@86 289
Nenue@86 290 D.DeepCopy(profileTemplate, currentProfile, id, name)
Nenue@86 291
Nenue@86 292
Nenue@66 293 currentProfile.char[playerRealm] = currentProfile.char[playerRealm] or {}
Nenue@66 294 if currentProfile.workspace then
Nenue@79 295 DEVIAN_WORKSPACE = true
Nenue@91 296 DEVIAN_PNAME = currentProfile.name
Nenue@89 297 DEVIAN_PID = id
Nenue@66 298 setprinthandler(D.Message)
Nenue@66 299 else
Nenue@79 300 DEVIAN_WORKSPACE = false
Nenue@93 301 DEVIAN_PNAME = nil
Nenue@93 302 print = nop
Nenue@66 303 end
Nenue@89 304 DEVIAN_PID =id
Nenue@66 305
Nenue@98 306
Nenue@98 307 -- Attempt to fix bad data
Nenue@98 308 --@debug@
Nenue@98 309 MINOR = 70100
Nenue@98 310 --@end-debug@
Nenue@98 311 if (currentProfile.lastUpdateFix or 0) < MINOR then
Nenue@98 312 D.FixProfile(true)
Nenue@98 313 end
Nenue@98 314
Nenue@98 315
Nenue@66 316 D.unlisted = currentProfile.unlisted
Nenue@66 317 D.channels = currentProfile.channels
Nenue@66 318 D.tags = currentProfile.tags
Nenue@66 319 D.channelinfo = currentProfile.channels
Nenue@66 320 D.char = currentProfile.char[playerRealm]
Nenue@66 321 D.global = currentProfile.global
Nenue@66 322 D.num_channels = currentProfile.num_channels
Nenue@66 323 D.enabled = currentProfile.enabled
Nenue@66 324 D.sig = {}
Nenue@66 325 D.sigID = {}
Nenue@66 326 D.IDsig = {}
Nenue@72 327 D.dock = _G.DevianDock
Nenue@66 328 D.dock.buttons = D.dock.buttons or {}
Nenue@66 329
Nenue@98 330
Nenue@98 331
Nenue@66 332 return id, name
Nenue@66 333 end
Nenue@66 334
Nenue@66 335 local targetGlobal, targetChar
Nenue@86 336 D.Command = function (cmd)
Nenue@66 337 local list_id, scan_func, reload
Nenue@86 338
Nenue@14 339 local args = {}
Nenue@86 340 if cmd then
Nenue@86 341 local i, j = 0, 0
Nenue@86 342 repeat
Nenue@86 343 i, j = cmd:find("%S+", j+1)
Nenue@86 344 if i and j then
Nenue@86 345 tinsert(args, cmd:sub(i, j))
Nenue@86 346 end
Nenue@86 347
Nenue@86 348 until not(i or j)
Nenue@14 349 end
Nenue@14 350 local mode, tag, dest = unpack(args)
Nenue@0 351
Nenue@86 352
Nenue@14 353 -- no args, toggle ui
Nenue@86 354 if mode == 'rc' then
Nenue@93 355 return D:ResetChannels(tag)
Nenue@86 356 elseif mode == 'stack' then
Nenue@14 357 return D:StackFrames()
Nenue@14 358 elseif mode == 'grid' then
Nenue@14 359 return D:DistributeFrames()
Nenue@14 360 elseif mode == 'tag' then -- tagging
Nenue@93 361 return D:Tag(tag, dest)
Nenue@73 362 elseif mode == 'new' then
Nenue@93 363 return D:New(tag)
Nenue@93 364 elseif mode == 'dock' then
Nenue@93 365 D.db.dockPoint = tag
Nenue@93 366 return D:UpdateDock()
Nenue@73 367 elseif mode == 'remove' then
Nenue@93 368 return D:Remove(tag)
Nenue@89 369 elseif mode ~= nil then
Nenue@89 370 -- profile selector or save command
Nenue@66 371 if mode == 'save' then
Nenue@66 372 list_id = tonumber(tag)
Nenue@89 373 else
Nenue@89 374 list_id = tonumber(mode)
Nenue@89 375 end
Nenue@89 376
Nenue@89 377 if not list_id then
Nenue@89 378 if db.profilesName[tostring(list_id)] then
Nenue@89 379 list_id = db.profilesName[tostring(list_id)]
Nenue@89 380 else
Nenue@89 381
Nenue@89 382 D:Print(L('Unable to resolve profile ID/name', list_id, dest))
Nenue@89 383 return
Nenue@66 384 end
Nenue@89 385 end
Nenue@89 386
Nenue@89 387
Nenue@89 388 if mode == 'save' then
Nenue@66 389 D.Profile(list_id, dest)
Nenue@66 390 scan_func = D.Save
Nenue@89 391
Nenue@89 392
Nenue@89 393 local name = currentProfile.name
Nenue@89 394 if dest then
Nenue@89 395 dest = dest:gsub("$%s+", ''):gsub("%s+^", '')
Nenue@89 396 if dest then
Nenue@89 397 if name then
Nenue@89 398 db.profilesName[name] = nil
Nenue@89 399 end
Nenue@89 400 db.profiles[list_id].name = dest
Nenue@89 401 db.profilesName[dest] = list_id
Nenue@92 402
Nenue@92 403 name = dest
Nenue@89 404 end
Nenue@89 405 end
Nenue@89 406
Nenue@89 407
Nenue@89 408 D:Print("Profile |cFFFFFF00".. list_id .."|r:|cFF00FFFF".. name .."|r saved.")
Nenue@66 409 else
Nenue@32 410
Nenue@89 411 if db.profiles[list_id] then
Nenue@89 412 D.LoadMessage ("Switched profiles.")
Nenue@89 413 if list_id ~= db.main_profile then
Nenue@89 414 db.last_profile = list_id
Nenue@89 415 end
Nenue@89 416 db.current_profile = list_id
Nenue@89 417 scan_func = D.Load
Nenue@89 418 else
Nenue@89 419 return D:PrintHelp()
Nenue@89 420 end
Nenue@36 421
Nenue@0 422 end
Nenue@32 423 elseif mode == nil then
Nenue@66 424 list_id = (db.current_profile ~= db.main_profile) and db.main_profile or db.last_profile
Nenue@77 425 D.LoadMessage ("Switched between main and recent profile ("..db.current_profile..' and '..list_id..')')
Nenue@66 426 db.current_profile = list_id
Nenue@66 427 scan_func = D.Load
Nenue@32 428 else
Nenue@89 429
Nenue@89 430
Nenue@32 431 return D:PrintHelp()
Nenue@0 432 end
Nenue@77 433
Nenue@77 434 if not db.profiles[list_id] then
Nenue@77 435 db.profiles[list_id] = {global = {}, char = {} }
Nenue@77 436 D.LoadMessage ("Starting profile #|cFF00FFFF".. list_id..'|r')
Nenue@77 437 end
Nenue@67 438 if not db.profiles[list_id].char[playerRealm] then
Nenue@67 439 db.profiles[list_id].char[playerRealm] = {}
Nenue@67 440 end
Nenue@67 441
Nenue@66 442 targetGlobal = db.profiles[list_id].global
Nenue@66 443 targetChar = db.profiles[list_id].char[playerRealm]
Nenue@32 444
Nenue@67 445
Nenue@66 446 if scan_func then
Nenue@93 447 wipe(charStates)
Nenue@66 448 for id, name, enableState, globalState in D.Addons() do
Nenue@66 449 scan_func(id, name, enableState, globalState)
Nenue@0 450 end
Nenue@0 451 end
Nenue@0 452
Nenue@66 453 if scan_func == D.Load then
Nenue@72 454 _G.ReloadUI()
Nenue@93 455 if AddonList_Update then
Nenue@93 456 AddonList_Update()
Nenue@93 457 end
Nenue@93 458 elseif (scan_func == D.Save) then
Nenue@93 459 print('reckoning')
Nenue@93 460 local updated = {}
Nenue@93 461 for addon, newState in pairs(charStates) do
Nenue@93 462 for character, addons in pairs(db.profiles[list_id].char) do
Nenue@93 463 if addons[addon] then
Nenue@93 464 print(addon, addons[addon], '::', newState)
Nenue@93 465 if (addons[addon] ~= newState) then
Nenue@93 466 addons[addon] = newState
Nenue@93 467 updated[character] = (updated[character] or 0) + 1
Nenue@93 468 end
Nenue@93 469
Nenue@93 470 end
Nenue@93 471
Nenue@93 472 end
Nenue@93 473 end
Nenue@93 474 for character, numAddons in pairs(updated) do
Nenue@93 475 print(character, numAddons, 'settings')
Nenue@93 476 end
Nenue@93 477
Nenue@66 478 end
Nenue@93 479
Nenue@93 480
Nenue@66 481 D.Profile(db.current_profile)
Nenue@66 482 end
Nenue@66 483
Nenue@66 484 D.Addons = function()
Nenue@66 485 local playername = UnitName("player")
Nenue@66 486 return function(n, i)
Nenue@66 487 if i >= n then
Nenue@66 488 return nil
Nenue@66 489 end
Nenue@66 490
Nenue@66 491 i = i + 1
Nenue@66 492 local name = GetAddOnInfo(i)
Nenue@66 493 local enableState, globalState = GetAddOnEnableState(playername, i), GetAddOnEnableState(nil, i)
Nenue@66 494 return i, name, enableState, globalState
Nenue@66 495 end, GetNumAddOns(), 0
Nenue@66 496 end
Nenue@66 497
Nenue@66 498 D.Load = function(id, name, charState, globalState)
Nenue@93 499 print('load', tostring(name), tostring(charState), tostring(globalState))
Nenue@93 500 if targetGlobal[name] == 2 then
Nenue@93 501 EnableAddOn(id, true)
Nenue@93 502 elseif targetChar[name] == 2 then
Nenue@93 503 EnableAddOn(id, playerName)
Nenue@93 504 elseif targetGlobal[name] == 0 then
Nenue@93 505 DisableAddOn(id, true)
Nenue@93 506 elseif targetChar[name] == 0 then
Nenue@93 507 DisableAddOn(id, playerName)
Nenue@93 508 end
Nenue@93 509
Nenue@93 510 if not (targetChar[name] or targetGlobal[name]) then
Nenue@66 511 tinsert(D.unlisted, name)
Nenue@66 512 end
Nenue@93 513
Nenue@66 514 end
Nenue@93 515
Nenue@93 516
Nenue@66 517 D.Save = function(id, name, charState, globalState)
Nenue@93 518 if (charState ~= 0) or (globalState ~= 0) then
Nenue@93 519 print('save', id, name, playerRealm .. ': '.. charState, 'All: '.. globalState)
Nenue@93 520 end
Nenue@93 521
Nenue@66 522 targetGlobal[name] = globalState
Nenue@66 523 targetChar[name] = charState
Nenue@93 524
Nenue@93 525 -- if enabling/disabling globally
Nenue@93 526 if globalState ~= 1 then
Nenue@93 527 charStates[name] = globalState
Nenue@93 528 end
Nenue@66 529 end
Nenue@57 530
Nenue@98 531 D.UpdateTags = function()
Nenue@98 532 wipe(registeredTags)
Nenue@99 533 for index, channel in ipairs(D.channels) do
Nenue@99 534 for _, tag in ipairs(channel.tags) do
Nenue@99 535 registeredTags[tag] = registeredTags[tag] or {}
Nenue@99 536 tinsert(registeredTags[tag], D.console[index])
Nenue@98 537 end
Nenue@98 538 end
Nenue@98 539 end
Nenue@98 540
Nenue@99 541 D.Tag = function(self, tag, id)
Nenue@66 542 local sig
Nenue@99 543 if tag and id then
Nenue@66 544 --@debug@
Nenue@66 545 --print(tag, dest)
Nenue@66 546 --@end-debug@
Nenue@66 547
Nenue@66 548 -- convert to ID
Nenue@99 549 local channel, sig
Nenue@99 550 if tonumber(id) == nil then
Nenue@99 551 sig = id
Nenue@99 552 if D.sigID[id] then
Nenue@99 553 id = D.sigID[id]
Nenue@99 554 channel = D.channels[id]
Nenue@66 555 end
Nenue@57 556 else
Nenue@99 557 id = tonumber(id)
Nenue@99 558 channel = D.channels[id]
Nenue@32 559 end
Nenue@66 560
Nenue@99 561 -- if channel is still nil, create one
Nenue@99 562 if not channel then
Nenue@99 563 id = #D.channels + 1
Nenue@99 564 D:Print(L('New channel created', (sig and (id..':'..sig)) or id))
Nenue@99 565 channel = D:GetOrCreateChannel(id, sig)
Nenue@66 566 else
Nenue@99 567 sig = channel.signature
Nenue@66 568 end
Nenue@66 569 --@debug@
Nenue@66 570 --print('3 tag,dest,channel.sig=',tag, dest, channel.signature)--@end-debug@
Nenue@66 571
Nenue@66 572 if not currentProfile.tags[tag] then -- no tag table?
Nenue@99 573 currentProfile.tags[tag] = {}
Nenue@66 574 end
Nenue@66 575
Nenue@99 576 local existingTag = tContains(channel.tags, tag)
Nenue@99 577 if existingTag then -- is tag set?
Nenue@99 578
Nenue@99 579 for i, tag in ipairs(channel.tags) do
Nenue@99 580 if tag == tag then
Nenue@99 581 tremove(channel.tags, i)
Nenue@99 582 D:Print(L('Tag removed from channel', tag, channel.index, channel.signature))
Nenue@99 583 break
Nenue@99 584 end
Nenue@99 585 end
Nenue@66 586 else
Nenue@99 587 tinsert(channel.tags, tag)
Nenue@98 588 D:Print(L('Tag added to channel', tag, channel.index, channel.signature))
Nenue@66 589 end
Nenue@98 590 D.UpdateTags()
Nenue@98 591 DevianDock:Update()
Nenue@66 592 else
Nenue@66 593 D:Print(L['Command tag help'])
Nenue@0 594 end
Nenue@0 595 end
Nenue@0 596
Nenue@86 597 D.ResetChannels = function(self, profile)
Nenue@86 598 currentProfile.current_channel = 1
Nenue@86 599 currentProfile.primary_channel = 1
Nenue@86 600 currentProfile.channels = {}
Nenue@86 601 D.DeepCopy(profileTemplate.channels, currentProfile.channels)
Nenue@86 602 currentProfile.tags = {}
Nenue@86 603 D.LoadMessage('Profile reset.')
Nenue@86 604 ReloadUI()
Nenue@86 605 end
Nenue@86 606
Nenue@73 607 D.New = function(self, tag)
Nenue@73 608 if tag and not self.sigID[tag] then
Nenue@73 609 local id = D.max_channel + 1
Nenue@73 610 D.SetChannel(tag, id)
Nenue@73 611 end
Nenue@73 612 end
Nenue@0 613
Nenue@73 614 D.Remove = function(self, dest)
Nenue@73 615 dest = D.sigID[dest] or tonumber(dest)
Nenue@73 616 if D.console[dest] and D.channels[dest] then
Nenue@73 617 for tag, tagDest in pairs(D.tags) do
Nenue@73 618 for i = #tagDest, 0 do
Nenue@73 619 -- work downward so we aren't skipping entries
Nenue@73 620 if tagDest[i] == dest then
Nenue@73 621 tremove(tagDest, i)
Nenue@73 622 end
Nenue@73 623 end
Nenue@73 624 end
Nenue@73 625 D.console[dest]:Hide()
Nenue@73 626 D.channels[dest] = nil
Nenue@73 627 tremove(D.console, dest)
Nenue@93 628 D.dock.buttons[dest]:SetShown(false)
Nenue@108 629 D.dock:Update()
Nenue@73 630 D:Print('Removed channel #'..dest)
Nenue@73 631 end
Nenue@73 632 end
Nenue@13 633
Nenue@77 634 --- Queue up a message to appear after UI reload
Nenue@77 635 function D.LoadMessage(msg)
Nenue@77 636
Nenue@77 637 tinsert(_G.DevianLoadMessage, msg)
Nenue@77 638 end
Nenue@77 639
Nenue@18 640 --- Creates a Devian-style output.
Nenue@18 641 -- The first argument describes the channel to output on, and the remaining arguments are concatenated in a manner similar to default print()
Nenue@18 642 -- This becomes the print handler when development mode is active. The original print() function is assigned to oldprint().
Nenue@18 643 -- @param Tag, signature, or numeric index of the channel to output on. Defaults to primary channel.
Nenue@18 644 -- @param ... Output contents.
Nenue@98 645 local default_sendq = {}
Nenue@66 646 function D.Message(prefix, ...)
Nenue@67 647 if not currentProfile.workspace then
Nenue@23 648 return D.oldprint(prefix, ...)
Nenue@23 649 end
Nenue@98 650 local print = D.oldprint
Nenue@57 651 prefix = tostring(prefix)
Nenue@57 652 if prefix == nil then
Nenue@55 653 prefix = 'nil*'
Nenue@1 654 end
Nenue@9 655
Nenue@98 656 local sendq = default_sendq
Nenue@30 657 local tag, id, tagged
Nenue@13 658 local byName = true
Nenue@98 659
Nenue@98 660 if registeredTags[prefix] then
Nenue@98 661 sendq = registeredTags[prefix]
Nenue@98 662 else
Nenue@98 663 if D.sig[prefix] then
Nenue@98 664 sendq[D.sig[prefix].index] = D.sig[prefix]
Nenue@98 665 elseif not tagged then
Nenue@98 666 sendq[1] = D.console[D.primary_channel]
Nenue@18 667 end
Nenue@18 668 end
Nenue@18 669
Nenue@98 670
Nenue@18 671
Nenue@9 672 -- color me timbers
Nenue@9 673 local pcolor
Nenue@18 674 if (not db.tagcolor[prefix]) and byName then
Nenue@86 675 -- numbers, use white
Nenue@86 676 if prefix:match('^%d+%.%d+') then
Nenue@73 677 pcolor = 'FFFFFF'
Nenue@73 678 else
Nenue@73 679 local c = {
Nenue@73 680 rand(64,255), rand(64,255), rand(64,255)
Nenue@73 681 }
Nenue@73 682 if c[1] > 223 and c[2] > 223 and c[3] > 223 then
Nenue@73 683 c[rand(1,3)] = rand(64,223)
Nenue@73 684 end
Nenue@73 685 db.tagcolor[prefix] = format('%02X%02X%02X', unpack(c))
Nenue@73 686 pcolor = db.tagcolor[prefix]
Nenue@0 687 end
Nenue@73 688 else
Nenue@73 689 pcolor = db.tagcolor[prefix]
Nenue@0 690 end
Nenue@0 691
Nenue@55 692 local buffer = {}
Nenue@0 693 for i = 1, select('#',...) do
Nenue@0 694 local var = select(i, ...)
Nenue@0 695
Nenue@0 696 if type(var) == 'table' then
Nenue@20 697 if type(var.GetName) == 'function' then
Nenue@72 698 var = '[table:'..tostring(var:GetName())..']'
Nenue@20 699 else
Nenue@32 700 var = '<'..tostring(var)..'>'
Nenue@20 701 end
Nenue@20 702
Nenue@0 703 elseif type(var) == 'boolean' then
Nenue@75 704 var = var and 'true' or 'false'
Nenue@0 705 elseif type(var) == 'function' then
Nenue@72 706 var = '['..tostring(var)..']'
Nenue@0 707 elseif type(var) == 'nil' then
Nenue@75 708 var = 'nil'
Nenue@60 709 else
Nenue@60 710 var = tostring(var)
Nenue@0 711 end
Nenue@0 712
Nenue@47 713 insert(buffer, var)
Nenue@0 714 end
Nenue@47 715 local message = concat(buffer, ' ')
Nenue@18 716 for id, channel in pairs(sendq) do
Nenue@55 717 if channel.width < 250 then
Nenue@72 718 prefix = sub(prefix, 0,2)
Nenue@55 719 end
Nenue@98 720 channel.out:AddMessage('|cFF'.. pcolor..prefix ..'|r ' .. message, 0.8, 0.8, 0.8)
Nenue@100 721 if not channel.newMessage then
Nenue@100 722 channel.newMessage = true
Nenue@100 723 if channel.Dock then
Nenue@100 724 channel.Dock:Update()
Nenue@100 725 end
Nenue@58 726 end
Nenue@108 727
Nenue@108 728
Nenue@18 729 end
Nenue@47 730 wipe(buffer)
Nenue@0 731 end
Nenue@0 732
Nenue@14 733
Nenue@32 734
Nenue@14 735
Nenue@32 736 function D:PrintHelp()
Nenue@32 737 D:Print("|cFFFFFF00/dvn|r",
Nenue@32 738 "\n |cFFFFFF00<number>|r - Loads a saved addon list. List 1 is treated as a gameplay profile and consoles will be disabled by default.")
Nenue@47 739 D:Print("|cFFFFFF00/dvc|r [<key>, ...]", "- Hides and show consoles. A list of channel keys can be passed to specify which ones get toggled.")
Nenue@32 740
Nenue@32 741 D:Print("|cFFFFFF00/resetdvn|r", "- Resets all but profile data SavedVariables.")
Nenue@32 742 D:Print("|cFFFFFF00/cleandvn|r", "- Fully resets SavedVariables, profiles and all.")
Nenue@32 743 end
Nenue@32 744
Nenue@66 745 local blocked = {profiles = true, debugmode = true}
Nenue@66 746 D.SetDefaults = function()
Nenue@72 747 local DevianDB = _G.DevianDB
Nenue@66 748 for k,v in pairs(DevianDB) do
Nenue@66 749 if not blocked[k] then
Nenue@66 750 DevianDB[k] = nil
Nenue@60 751 end
Nenue@60 752 end
Nenue@66 753 for k,v in pairs(defaults) do
Nenue@66 754 if not blocked[k] then
Nenue@66 755 DevianDB[k] = v
Nenue@60 756 end
Nenue@60 757 end
Nenue@73 758
Nenue@77 759 D.LoadMessage "Non-user SavedVars have been reset."
Nenue@72 760 _G.ReloadUI()
Nenue@60 761 end
Nenue@66 762 D.SetDefaultsAll = function ()
Nenue@72 763 _G.DevianDB = nil
Nenue@77 764 D.LoadMessage "All SavedVars wiped."
Nenue@72 765 _G.ReloadUI()
Nenue@66 766 end
Nenue@73 767
Nenue@73 768 D.UnsetColors = function()
Nenue@73 769 db.tagcolor = {}
Nenue@73 770 D:Print('Tag color cache cleared.')
Nenue@73 771 end
Nenue@45 772
Nenue@33 773
Nenue@89 774 function D.ConsoleCommand (cmd)
Nenue@100 775 DevianDock:ToggleAll()
Nenue@89 776 end
Nenue@87 777
Nenue@66 778
Nenue@98 779 function DevianCore:Initialize()
Nenue@81 780 L = D.L
Nenue@13 781
Nenue@33 782 -- pull defaults
Nenue@98 783 if not DevianDB then
Nenue@98 784 DevianDB = defaults
Nenue@9 785 end
Nenue@98 786 D.db = _G.DevianDB
Nenue@9 787 db = _G.DevianDB
Nenue@0 788
Nenue@66 789 ---
Nenue@77 790 if #_G.DevianLoadMessage >= 1 then
Nenue@77 791 for i, msg in ipairs(_G.DevianLoadMessage) do
Nenue@77 792 D:Print(msg)
Nenue@77 793 end
Nenue@77 794
Nenue@77 795 table.wipe(_G.DevianLoadMessage)
Nenue@0 796 end
Nenue@0 797
Nenue@66 798
Nenue@89 799 -- commands
Nenue@89 800 local cmdlist = {
Nenue@89 801 ['dvn'] = "Command",
Nenue@89 802 ['devian'] = "Command",
Nenue@89 803 ['dvc'] = "ConsoleCommand",
Nenue@89 804 ['dvncolors'] = "UnsetColors",
Nenue@89 805 ['cleandvn'] = "SetDefaultsAll",
Nenue@89 806 ['resetdvn'] = "SetDefaults",
Nenue@89 807 }
Nenue@89 808 for cmd, func in pairs(cmdlist) do
Nenue@89 809 local CMD = cmd:upper()
Nenue@89 810 _G['SLASH_' .. CMD .. '1'] = "/"..cmd
Nenue@89 811
Nenue@89 812 if type(func == 'string') then
Nenue@93 813 --print('SLASH_' .. CMD .. '1','/'.. cmd, func)
Nenue@89 814 SlashCmdList[CMD] = D[func]
Nenue@89 815 else
Nenue@93 816 --print('SLASH_' .. CMD .. '1','/'.. cmd, func)
Nenue@89 817 SlashCmdList[CMD] = func
Nenue@89 818 end
Nenue@89 819 end
Nenue@89 820
Nenue@66 821 --- initialize the current profile
Nenue@66 822 local id, name = D.Profile(db.current_profile or 1)
Nenue@66 823 if currentProfile.workspace then
Nenue@100 824 tinsert(channels_report, 'Profile |cFFFFFF00'.. id ..'|r: |cFF00FF00'..currentProfile.name.. '|r')
Nenue@86 825 if D.channels[currentProfile.default_channel] then
Nenue@100 826 tinsert(channels_report, 'Primary: |cFFFFFF00#'..currentProfile.default_channel..'|r |cFF00FFFF'.. D.channels[currentProfile.default_channel].signature..'|r')
Nenue@86 827 end
Nenue@0 828 end
Nenue@13 829
Nenue@86 830
Nenue@98 831
Nenue@98 832 for index, cinfo in ipairs(D.channels) do
Nenue@98 833 --oldprint(index, cinfo.signature)
Nenue@66 834 if not D.primary_channel then
Nenue@98 835 D.primary_channel = index
Nenue@14 836 end
Nenue@98 837 D:GetOrCreateChannel(index)
Nenue@98 838 D.num_channels = #D.channels
Nenue@32 839 end
Nenue@100 840 if #channels_report >= 1 then
Nenue@100 841 D:Print(concat(channels_report, ', '))
Nenue@100 842 end
Nenue@100 843
Nenue@86 844 D.primary_channel = D.primary_channel or 1
Nenue@66 845 D.max_channel = max(D.max_channel, currentProfile.max_channel)
Nenue@66 846 if currentProfile.max_channel < D.max_channel then
Nenue@66 847 for i = currentProfile.max_channel, D.max_channel do
Nenue@66 848 D.console[i]:Hide()
Nenue@47 849 end
Nenue@36 850 end
Nenue@36 851
Nenue@98 852 D.UpdateTags()
Nenue@98 853
Nenue@66 854 if currentProfile.workspace then
Nenue@66 855 if D.console[currentProfile.current_channel] then
Nenue@69 856 --print('bringing', D.console[currentProfile.current_channel].signature, 'to the front')
Nenue@66 857 D.console[currentProfile.current_channel]:ToFront()
Nenue@66 858 -- bring the current channel to the front
Nenue@47 859 end
Nenue@98 860 DevianDock:Update()
Nenue@36 861 end
Nenue@66 862 end
Nenue@89 863
Nenue@98 864 function D:Print (...)
Nenue@98 865 local msg = '|cFF00FF44Devian|r:'
Nenue@98 866 for i = 1, select('#', ...) do
Nenue@98 867 msg = msg .. ' ' .. tostring(select(i, ...))
Nenue@98 868 end
Nenue@98 869 DEFAULT_CHAT_FRAME:AddMessage(msg)
Nenue@98 870 end
Nenue@98 871
Nenue@98 872 function D:GetActiveChannel()
Nenue@98 873 return D.console[currentProfile.current_channel]
Nenue@98 874 end
Nenue@98 875
Nenue@98 876 function D:GetOrCreateChannel(id, name)
Nenue@99 877 id = id or (#D.channels + 1)
Nenue@99 878
Nenue@98 879 local info = D.channels[id]
Nenue@99 880 if not info then
Nenue@99 881 --print('new channel')
Nenue@99 882 name = name or ('Channel ' .. id)
Nenue@99 883 info = {
Nenue@99 884 index = id,
Nenue@99 885 signature = name,
Nenue@99 886 tags = {}
Nenue@99 887 }
Nenue@99 888 D.DeepCopy(defaults.default_channel, info)
Nenue@99 889 D.channels[id] = info
Nenue@99 890 elseif not info.tags then
Nenue@99 891 -- fix old data?
Nenue@99 892 info.tags = {info.signature}
Nenue@99 893 oldprint(D.db)
Nenue@99 894 for tag, tagSet in pairs(D.tags) do
Nenue@99 895 for _, index in pairs(tagSet) do
Nenue@99 896 if index == id then
Nenue@99 897 tinsert(info.tags, tag)
Nenue@99 898 end
Nenue@99 899 end
Nenue@99 900 end
Nenue@99 901 end
Nenue@99 902
Nenue@98 903 local frame = D.console[id]
Nenue@100 904
Nenue@98 905 if not frame then
Nenue@98 906
Nenue@99 907 if DEVIAN_WORKSPACE then
Nenue@100 908 tinsert(channels_report, (info.index) .. ':' .. (info.signature) .. ' (|cFF00FFFF'.. concat(info.tags, '|r; |cFF00FFFF')..'|r)')
Nenue@99 909 end
Nenue@98 910 frame = CreateFrame('Frame', 'DevianConsole'..id, Devian, 'DevianConsoleTemplate')
Nenue@98 911 frame:SetID(id)
Nenue@98 912 D.console[id] = frame
Nenue@99 913 D.sigID[info.signature] = id
Nenue@98 914 end
Nenue@98 915
Nenue@98 916 frame:Setup(info)
Nenue@98 917 return frame
Nenue@98 918 end