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