Nenue@0
|
1 --- Modulizer framework
|
Nenue@0
|
2 -- OnInitialize
|
Nenue@0
|
3 -- OnUpdate
|
Nenue@0
|
4 -- OnEnable -- run when GetSpecialization() returns true
|
Nenue@0
|
5
|
Nenue@0
|
6 local ADDON, A = ...
|
Nenue@0
|
7 Veneer = Veneer or CreateFrame('Frame', 'Veneer', UIParent)
|
Nenue@0
|
8 local B = Veneer
|
Nenue@0
|
9 local wipe, min, max, random, tinsert = table.wipe, math.min, math.max, math.random, table.insert
|
Nenue@0
|
10 local pairs, ipairs, select, unpack, _G = pairs, ipairs, select, unpack, _G
|
Nenue@0
|
11 local type, tostring, format = type, tostring, string.format
|
Nenue@0
|
12 A.frame = B
|
Nenue@0
|
13
|
Nenue@0
|
14 --- Cache tables
|
Nenue@0
|
15 local initOnced
|
Nenue@0
|
16 local modules = {}
|
Nenue@0
|
17 local queuedModules = {}
|
Nenue@0
|
18 local moduleStack = {
|
Nenue@0
|
19 }
|
Nenue@0
|
20
|
Nenue@0
|
21 --- Various region categories
|
Nenue@0
|
22 B.displays = {}
|
Nenue@0
|
23 B.configLayers = {}
|
Nenue@0
|
24 B.configLayersRef = {}
|
Nenue@0
|
25
|
Nenue@0
|
26 --@debug@
|
Nenue@0
|
27 --- Generates a print handler pointing to a static channel signature
|
Nenue@0
|
28 -- @usage func = B.print(sig)
|
Nenue@0
|
29 -- @param sig channel name or number
|
Nenue@0
|
30 local printfuncs = {}
|
Nenue@0
|
31 B.print = function(pref, ...)
|
Nenue@0
|
32 if Devian and Devian.InWorkspace() then
|
Nenue@0
|
33 printfuncs[pref] = printfuncs[pref] or function(...) print(pref, ...) end
|
Nenue@0
|
34
|
Nenue@0
|
35 return printfuncs[pref]
|
Nenue@0
|
36 else
|
Nenue@0
|
37 return function () end
|
Nenue@0
|
38 end
|
Nenue@0
|
39 end
|
Nenue@0
|
40
|
Nenue@0
|
41 local rgb = {}
|
Nenue@0
|
42 local getcolor = function()
|
Nenue@0
|
43 local n, p = 0, 4
|
Nenue@0
|
44 for i = 1, 3 do
|
Nenue@0
|
45 rgb[i] = min(random(n,p) * 64, 255)
|
Nenue@0
|
46 if rgb[i] == 255 then
|
Nenue@0
|
47 p = 4
|
Nenue@0
|
48 elseif rgb[i] > 0 then
|
Nenue@0
|
49 n = 2
|
Nenue@0
|
50 end
|
Nenue@0
|
51 end
|
Nenue@0
|
52 return unpack(rgb)
|
Nenue@0
|
53 end
|
Nenue@0
|
54
|
Nenue@0
|
55 local color = {}
|
Nenue@0
|
56 local fprints = {}
|
Nenue@0
|
57 B.fprint = function()
|
Nenue@0
|
58 if not (Devian and Devian.InWorkspace()) then
|
Nenue@0
|
59 return function() end
|
Nenue@0
|
60 end
|
Nenue@0
|
61
|
Nenue@0
|
62
|
Nenue@0
|
63 local sig = debugstack(2,1)
|
Nenue@0
|
64 if fprints[sig] then
|
Nenue@0
|
65 return fprints[sig]
|
Nenue@0
|
66 end
|
Nenue@0
|
67
|
Nenue@0
|
68 local func = sig:match("%`(%a+)%'")
|
Nenue@0
|
69 if not func then
|
Nenue@0
|
70 func = sig:match("<(.-)>")
|
Nenue@0
|
71 end
|
Nenue@0
|
72 func = func:gsub('(%l+)(%u)', function(a, b) return a:sub(0,2) .. b end, 1)
|
Nenue@0
|
73 func = func:gsub('^.+%\\', '')
|
Nenue@0
|
74 if not func then
|
Nenue@0
|
75 func = 'noname'
|
Nenue@0
|
76 end
|
Nenue@0
|
77
|
Nenue@0
|
78 local r, g, b = getcolor()
|
Nenue@0
|
79 color[sig] = color[sig] or format('|cFF%02X%02X%02X%s|r', r, g, b, func)
|
Nenue@0
|
80
|
Nenue@0
|
81 --print(color[func] .. ' ( ' .. table.concat(args, ', ')..' )' )
|
Nenue@0
|
82 func = B.print(func)
|
Nenue@0
|
83 fprints[sig] = func
|
Nenue@0
|
84 return func
|
Nenue@0
|
85 end
|
Nenue@0
|
86
|
Nenue@0
|
87 --@end-debug@
|
Nenue@0
|
88 --[=[@non-debug@
|
Nenue@0
|
89 B.print = function() end
|
Nenue@0
|
90 --@end-non-debug@]=]
|
Nenue@0
|
91
|
Nenue@0
|
92 -- for the Mikk script
|
Nenue@0
|
93 -- GLOBALS: NUM_LE_RAID_BUFF_TYPES
|
Nenue@0
|
94 -- GLOBALS: BUFF_FLASH_TIME_ON, BUFF_FLASH_TIME_OFF, BUFF_MIN_ALPHA, BUFF_WARNING_TIME, BUFF_DURATION_WARNING_TIME
|
Nenue@0
|
95 -- GLOBALS: BUFFS_PER_ROW, BUFF_MAX_DISPLAY, BUFF_ACTUAL_DISPLAY, DEBUFF_MAX_DISPLAY, DEBUFF_ACTUAL_DISPLAY, BUFF_ROW_SPACING
|
Nenue@0
|
96 -- GLOBALS: CONSOLIDATED_BUFFS_PER_ROW, CONSOLIDATED_BUFF_ROW_HEIGHT, NUM_TEMP_ENCHANT_FRAMES
|
Nenue@0
|
97 -- GLOBALS: BUFF_BUTTON_HEIGHT, BUFF_FRAME_BASE_EXTENT, BUFF_HORIZ_SPACING
|
Nenue@0
|
98
|
Nenue@0
|
99 local print = B.print('Bfl')
|
Nenue@0
|
100
|
Nenue@0
|
101 --- Template for making perpendicular traversals of the displays structure; also makes sure the table is there
|
Nenue@0
|
102 B.Abstract = function(dest, key, table)
|
Nenue@0
|
103 if table then
|
Nenue@0
|
104 for _, v in pairs(dest) do
|
Nenue@0
|
105 v[key] = {}
|
Nenue@0
|
106 end
|
Nenue@0
|
107 end
|
Nenue@0
|
108 B[key] = setmetatable({}, {
|
Nenue@0
|
109 __index = function(t, k)
|
Nenue@0
|
110 return dest[k][key]
|
Nenue@0
|
111 end,
|
Nenue@0
|
112 __newindex = function(_, k, v)
|
Nenue@0
|
113 print('abstract write ('..key..'):', k)
|
Nenue@0
|
114 dest[k][key] = v
|
Nenue@0
|
115 end,
|
Nenue@0
|
116 __tostring = function() return 'Abstract:'..key..'' end
|
Nenue@0
|
117 })
|
Nenue@0
|
118
|
Nenue@0
|
119
|
Nenue@0
|
120 return B[key]
|
Nenue@0
|
121 end
|
Nenue@0
|
122
|
Nenue@0
|
123
|
Nenue@0
|
124 --- localize for speed
|
Nenue@0
|
125 local layers, refs, displays = B.configLayers, B.configLayersRef, B.displays
|
Nenue@0
|
126
|
Nenue@0
|
127 local ModulesCall = function(func)
|
Nenue@0
|
128
|
Nenue@0
|
129 local n = 0
|
Nenue@0
|
130 for i = 1, #moduleStack do
|
Nenue@0
|
131 print('calling level '..i)
|
Nenue@0
|
132 local stackset = moduleStack[i]
|
Nenue@0
|
133
|
Nenue@0
|
134 for name, module in pairs(stackset) do
|
Nenue@0
|
135 n = n + 1
|
Nenue@0
|
136 print(n..' '..name..'.'..func..'()')
|
Nenue@0
|
137
|
Nenue@0
|
138
|
Nenue@0
|
139 if module[func] then
|
Nenue@0
|
140 module[func](module)
|
Nenue@0
|
141 end
|
Nenue@0
|
142 end
|
Nenue@0
|
143 end
|
Nenue@0
|
144 end
|
Nenue@0
|
145
|
Nenue@0
|
146
|
Nenue@0
|
147 local Enable = function()
|
Nenue@0
|
148 end
|
Nenue@0
|
149
|
Nenue@0
|
150 --- The things that happen repeatedly
|
Nenue@0
|
151 local Init = function ()
|
Nenue@0
|
152 end
|
Nenue@0
|
153
|
Nenue@0
|
154
|
Nenue@0
|
155 --- Things that happen immediately upon entering world
|
Nenue@0
|
156 local InitOnce = function()
|
Nenue@0
|
157 print('entering world first time')
|
Nenue@0
|
158 local defaults = B.ConfDefaults
|
Nenue@0
|
159 print('|cFFFFFF00Veneer|r')
|
Nenue@0
|
160 if not VeneerData then
|
Nenue@0
|
161 VeneerData = {}
|
Nenue@0
|
162 for k,v in pairs(defaults) do
|
Nenue@0
|
163 VeneerData[k] = v
|
Nenue@0
|
164 end
|
Nenue@0
|
165 print('Veneer defaults being used.')
|
Nenue@0
|
166 end
|
Nenue@0
|
167
|
Nenue@0
|
168 B.Conf = setmetatable(VeneerData, {__index = function(_, k) return defaults[k] end})
|
Nenue@0
|
169
|
Nenue@0
|
170 -- suffix tables
|
Nenue@0
|
171 for name, display in pairs(displays) do
|
Nenue@0
|
172 display.conf = setmetatable({}, {
|
Nenue@0
|
173 __index = function(_, k)
|
Nenue@0
|
174 --print('config check '.. name .. k)
|
Nenue@0
|
175 return B.Conf[name .. k] or B.Conf['BuffButton' .. k]
|
Nenue@0
|
176 end,
|
Nenue@0
|
177 __newindex = function(_, k , v)
|
Nenue@0
|
178 B.Conf[name..k] = v
|
Nenue@0
|
179 end,
|
Nenue@0
|
180 })
|
Nenue@0
|
181 end
|
Nenue@0
|
182
|
Nenue@0
|
183 -- To ensure that modules are run in controlled order, walk the dependency list; if the dep shows up
|
Nenue@0
|
184 -- in the loaded manifest, remove the value. If the dep list isn't empty, move that module to the next
|
Nenue@0
|
185 -- layer.
|
Nenue@0
|
186 local loaded = {}
|
Nenue@0
|
187 local stackLevels = #moduleStack
|
Nenue@0
|
188 local i = 1
|
Nenue@0
|
189 moduleStack[1] = modules
|
Nenue@0
|
190 repeat
|
Nenue@0
|
191 print('setting init level '.. i)
|
Nenue@0
|
192 local queue = moduleStack[i]
|
Nenue@0
|
193 for name, module in pairs(queue) do
|
Nenue@0
|
194
|
Nenue@0
|
195 if queuedModules[name] and #queuedModules[name] > 0 then
|
Nenue@0
|
196 local p = #queuedModules[name]
|
Nenue@0
|
197 for j = 1, p do
|
Nenue@0
|
198 local dep = queuedModules[name][j]
|
Nenue@0
|
199
|
Nenue@0
|
200 if loaded[dep] then
|
Nenue@0
|
201 print( ' ' .. dep .. ' OK')
|
Nenue@0
|
202 queuedModules[name][j] = nil
|
Nenue@0
|
203 for k = j, p do
|
Nenue@0
|
204 print(' shift ' .. (k+1) .. ' ('..tostring(queuedModules[name][k+1])..') to ' .. k ..'')
|
Nenue@0
|
205 queuedModules[name][k] = queuedModules[name][k+1]
|
Nenue@0
|
206 end
|
Nenue@0
|
207 end
|
Nenue@0
|
208 end
|
Nenue@0
|
209
|
Nenue@0
|
210 if #queuedModules[name] == 0 then
|
Nenue@0
|
211 queuedModules[name] = nil
|
Nenue@0
|
212 print(' |cFF00FFFF'.. name ..'|r deps OK')
|
Nenue@0
|
213 loaded[name] = true
|
Nenue@0
|
214 else
|
Nenue@0
|
215
|
Nenue@0
|
216 print(' |cFFFF8800' .. name ..'|r pending')
|
Nenue@0
|
217 local next = i+1
|
Nenue@0
|
218 if not moduleStack[next] then
|
Nenue@0
|
219 moduleStack[next] = {}
|
Nenue@0
|
220 end
|
Nenue@0
|
221 stackLevels = next
|
Nenue@0
|
222 moduleStack[next][name] = module
|
Nenue@0
|
223 queue[name] = nil
|
Nenue@0
|
224 end
|
Nenue@0
|
225
|
Nenue@0
|
226 else
|
Nenue@0
|
227 print(' |cFF00FF00'.. name ..'|r no deps')
|
Nenue@0
|
228 loaded[name] = true
|
Nenue@0
|
229 end
|
Nenue@0
|
230 end
|
Nenue@0
|
231 i = i + 1
|
Nenue@0
|
232 until i > stackLevels
|
Nenue@0
|
233
|
Nenue@0
|
234
|
Nenue@0
|
235 for level, batch in ipairs(moduleStack) do
|
Nenue@0
|
236 print('config level', level)
|
Nenue@0
|
237 for name, module in pairs(batch) do
|
Nenue@0
|
238 print('integrity check', name)
|
Nenue@0
|
239
|
Nenue@0
|
240 --[===[@non-debug@
|
Nenue@0
|
241 if module.defaults and not VeneerData[name] then
|
Nenue@0
|
242 --@end-non-debug@]===]
|
Nenue@0
|
243 print('Adding defaults from module ', name)
|
Nenue@0
|
244 VeneerData[name] = module.default
|
Nenue@0
|
245 --[===[@non-debug@
|
Nenue@0
|
246 end
|
Nenue@0
|
247 --@end-non-debug@]===]
|
Nenue@0
|
248 end
|
Nenue@0
|
249 end
|
Nenue@0
|
250 -- remove from existing
|
Nenue@0
|
251 end
|
Nenue@0
|
252
|
Nenue@0
|
253 --- Fires an update to all modules
|
Nenue@0
|
254 local lastUpdate
|
Nenue@0
|
255 function B.UpdateAll(...)
|
Nenue@0
|
256 lastUpdate = GetTime()
|
Nenue@0
|
257 ModulesCall('OnUpdate', lastUpdate)
|
Nenue@0
|
258 end
|
Nenue@0
|
259
|
Nenue@0
|
260 B:RegisterEvent('PLAYER_ENTERING_WORLD')
|
Nenue@0
|
261 B:SetScript('OnEvent', function(self, event)
|
Nenue@0
|
262 if event == 'PLAYER_ENTERING_WORLD' then
|
Nenue@0
|
263 if not initOnced then
|
Nenue@0
|
264 InitOnce()
|
Nenue@0
|
265 ModulesCall('OnInitialize')
|
Nenue@0
|
266 initOnced = true
|
Nenue@0
|
267 C_Timer.After(1, function()
|
Nenue@0
|
268 if GetSpecialization() then
|
Nenue@0
|
269 print(GetSpecialization(), 'enabling')
|
Nenue@0
|
270 ModulesCall('OnEnable')
|
Nenue@0
|
271 B:SetScript('OnUpdate', nil)
|
Nenue@0
|
272 end
|
Nenue@0
|
273
|
Nenue@0
|
274 end)
|
Nenue@0
|
275 end
|
Nenue@0
|
276
|
Nenue@0
|
277 end
|
Nenue@0
|
278
|
Nenue@0
|
279 B.UpdateAll()
|
Nenue@0
|
280 end)
|
Nenue@0
|
281
|
Nenue@0
|
282 --- Modulizer method
|
Nenue@0
|
283 --
|
Nenue@0
|
284 function B:RegisterModule (name, module, ...)
|
Nenue@0
|
285 if modules[name] then
|
Nenue@0
|
286 print('pulling modules[|cFFFF8800'.. tostring(name) ..'|r]')
|
Nenue@0
|
287 return modules[name]
|
Nenue@0
|
288 end
|
Nenue@0
|
289
|
Nenue@0
|
290 print('new module |cFF00BBFF'.. tostring(name) ..'|r')
|
Nenue@0
|
291 if module then
|
Nenue@0
|
292 if modules[name] then
|
Nenue@0
|
293 error("Module table for '"..tostring(name).."' already exists.")
|
Nenue@0
|
294 end
|
Nenue@0
|
295 else
|
Nenue@0
|
296 module = CreateFrame('Frame', 'Veneer' .. tostring(name) .. 'Handler', B, 'VeneerHandlerTemplate')
|
Nenue@0
|
297 end
|
Nenue@0
|
298 modules[name] = module
|
Nenue@0
|
299 if select('#', ...) >= 1 then
|
Nenue@0
|
300 local numDeps = select('#', ...)
|
Nenue@0
|
301 print(' '..numDeps..' deps detected')
|
Nenue@0
|
302 for i = 1, numDeps do
|
Nenue@0
|
303 local dep = select(i, ...)
|
Nenue@0
|
304 -- means that init/enable funcs are ordered to run after deps do their things
|
Nenue@0
|
305 queuedModules[name] = queuedModules[name] or {}
|
Nenue@0
|
306 tinsert(queuedModules[name], dep)
|
Nenue@0
|
307 print(' needs '..dep)
|
Nenue@0
|
308 end
|
Nenue@0
|
309 end
|
Nenue@0
|
310 return module
|
Nenue@0
|
311 end
|
Nenue@0
|
312
|
Nenue@0
|
313
|
Nenue@0
|
314 B.SetConfigLayers = function(frame)
|
Nenue@0
|
315 local print = B.fprint()
|
Nenue@0
|
316 if not frame.config then
|
Nenue@0
|
317 print(frame:GetName(), 'has no config layers')
|
Nenue@0
|
318 return
|
Nenue@0
|
319 end
|
Nenue@0
|
320 print('Registering config layers from', frame:GetName())
|
Nenue@0
|
321
|
Nenue@0
|
322 for i, subframe in ipairs(frame.config) do
|
Nenue@0
|
323 -- make sure there are no duplicates
|
Nenue@0
|
324 if not refs[subframe] then
|
Nenue@0
|
325 local key = #layers+1
|
Nenue@0
|
326 layers[key] = subframe
|
Nenue@0
|
327 refs[subframe] = key
|
Nenue@0
|
328 end
|
Nenue@0
|
329 print(' ', i, subframe:GetName())
|
Nenue@0
|
330 end
|
Nenue@0
|
331 end
|
Nenue@0
|
332
|
Nenue@0
|
333 B.RemoveConfigLayers = function(frame)
|
Nenue@0
|
334 local print = B.fprint()
|
Nenue@0
|
335 print('|cFFFF0000RemoveConfigLayers', frame:GetName())
|
Nenue@0
|
336 for i, subframe in pairs(layers) do
|
Nenue@0
|
337 if subframe:GetParent() == frame then
|
Nenue@0
|
338 print('|cFFFF8800 ', subframe:GetParent():GetName(), '|cFFFFFF00', subframe:GetName())
|
Nenue@0
|
339 layers[i]:Hide()
|
Nenue@0
|
340 layers[i] = nil
|
Nenue@0
|
341 refs[subframe] = nil
|
Nenue@0
|
342 end
|
Nenue@0
|
343 end
|
Nenue@0
|
344 end
|
Nenue@0
|
345
|
Nenue@0
|
346 B.UpdateConfigLayers = function()
|
Nenue@0
|
347 local print = B.fprint()
|
Nenue@0
|
348 local func = B.Conf.GuidesMode and 'Show' or 'Hide'
|
Nenue@0
|
349 local numAnchors = 0
|
Nenue@0
|
350 for name, display in pairs(displays) do
|
Nenue@0
|
351 numAnchors = numAnchors + 1
|
Nenue@0
|
352 display.anchor:EnableMouse(B.Conf.GuidesMode)
|
Nenue@0
|
353 if B.Conf.GuidesMode then
|
Nenue@0
|
354 display.anchor:SetScript('OnUpdate', display.anchor.OnUpdate)
|
Nenue@0
|
355 else
|
Nenue@0
|
356 display.anchor:SetScript('OnUpdate', nil)
|
Nenue@0
|
357
|
Nenue@0
|
358 for i, anchorButton in ipairs(display.anchor.anchorButton) do
|
Nenue@0
|
359 anchorButton:Hide()
|
Nenue@0
|
360 end
|
Nenue@0
|
361
|
Nenue@0
|
362 end
|
Nenue@0
|
363
|
Nenue@0
|
364 end
|
Nenue@0
|
365 for id, region in pairs(layers) do
|
Nenue@0
|
366 print(id, region:GetName(), func)
|
Nenue@0
|
367 region[func](region)
|
Nenue@0
|
368 end
|
Nenue@0
|
369
|
Nenue@0
|
370 print('['..func..'] updated', #layers, 'regions,', numAnchors, 'frames')
|
Nenue@0
|
371 end |