Mercurial > wow > buffalo2
comparison Veneer.lua @ 47:1a322b92dbfa
file cleanup
author | Nenue |
---|---|
date | Thu, 28 Apr 2016 05:54:21 -0400 |
parents | Init.lua@756e8aeb040b |
children | 9837069e366a |
comparison
equal
deleted
inserted
replaced
46:aa693607b813 | 47:1a322b92dbfa |
---|---|
1 --- Modulizer framework | |
2 -- OnInitialize | |
3 -- OnUpdate | |
4 -- OnEnable -- run when GetSpecialization() returns true | |
5 | |
6 local ADDON, A = ... | |
7 Veneer = Veneer or CreateFrame('Frame', 'Veneer', UIParent) | |
8 local B = Veneer | |
9 local wipe, min, max, random, tinsert, tremove = table.wipe, math.min, math.max, math.random, table.insert, table.remove | |
10 local pairs, ipairs, select, unpack, _G = pairs, ipairs, select, unpack, _G | |
11 local type, tostring, format = type, tostring, string.format | |
12 A.frame = B | |
13 | |
14 --- Cache tables | |
15 local initOnced | |
16 local modules = {} | |
17 local queuedModules = {} | |
18 local checkForConfig = {} | |
19 local moduleStack = { | |
20 } | |
21 | |
22 --- Utilities | |
23 B.wipeall = function (...) | |
24 for i = 1, select('#', ...) do | |
25 wipe(select(i, ...)) | |
26 end | |
27 end | |
28 | |
29 --- Various region categories | |
30 B.displays = {} | |
31 B.configLayers = {} | |
32 B.configLayersRef = {} | |
33 | |
34 | |
35 --@debug@ | |
36 --- Generates a print handler pointing to a static channel signature | |
37 -- @usage func = B.print(sig) | |
38 -- @param sig channel name or number | |
39 local printfuncs = {} | |
40 B.print = function(pref, ...) | |
41 if Devian and Devian.InWorkspace() then | |
42 printfuncs[pref] = printfuncs[pref] or function(...) print(pref, ...) end | |
43 | |
44 return printfuncs[pref] | |
45 else | |
46 return function () end | |
47 end | |
48 end | |
49 | |
50 local rgb = {} | |
51 local getcolor = function() | |
52 local n, p = 0, 4 | |
53 for i = 1, 3 do | |
54 rgb[i] = min(random(n,p) * 64, 255) | |
55 if rgb[i] == 255 then | |
56 p = 4 | |
57 elseif rgb[i] > 0 then | |
58 n = 2 | |
59 end | |
60 end | |
61 return unpack(rgb) | |
62 end | |
63 | |
64 local color = {} | |
65 local fprints = {} | |
66 B.fprint = function() | |
67 if not (Devian and Devian.InWorkspace()) then | |
68 return function() end | |
69 end | |
70 | |
71 | |
72 local sig = debugstack(2,1) | |
73 if fprints[sig] then | |
74 return fprints[sig] | |
75 end | |
76 | |
77 local func = sig:match("%`(%a+)%'") | |
78 if not func then | |
79 func = sig:match("<(.-)>") | |
80 end | |
81 func = func:gsub('(%l+)(%u)', function(a, b) return a:sub(0,2) .. b end, 1) | |
82 func = func:gsub('^.+%\\', '') | |
83 if not func then | |
84 func = 'noname' | |
85 end | |
86 | |
87 local r, g, b = getcolor() | |
88 color[sig] = color[sig] or format('|cFF%02X%02X%02X%s|r', r, g, b, func) | |
89 | |
90 --print(color[func] .. ' ( ' .. table.concat(args, ', ')..' )' ) | |
91 func = B.print(func) | |
92 fprints[sig] = func | |
93 return func | |
94 end | |
95 | |
96 --@end-debug@ | |
97 --[=[@non-debug@ | |
98 B.print = function() end | |
99 --@end-non-debug@]=] | |
100 | |
101 -- for the Mikk script | |
102 -- GLOBALS: NUM_LE_RAID_BUFF_TYPES | |
103 -- GLOBALS: BUFF_FLASH_TIME_ON, BUFF_FLASH_TIME_OFF, BUFF_MIN_ALPHA, BUFF_WARNING_TIME, BUFF_DURATION_WARNING_TIME | |
104 -- GLOBALS: BUFFS_PER_ROW, BUFF_MAX_DISPLAY, BUFF_ACTUAL_DISPLAY, DEBUFF_MAX_DISPLAY, DEBUFF_ACTUAL_DISPLAY, BUFF_ROW_SPACING | |
105 -- GLOBALS: CONSOLIDATED_BUFFS_PER_ROW, CONSOLIDATED_BUFF_ROW_HEIGHT, NUM_TEMP_ENCHANT_FRAMES | |
106 -- GLOBALS: BUFF_BUTTON_HEIGHT, BUFF_FRAME_BASE_EXTENT, BUFF_HORIZ_SPACING | |
107 | |
108 local print = B.print('Bfl') | |
109 | |
110 --- Template for making perpendicular traversals of the displays structure; also makes sure the table is there | |
111 B.Abstract = function(dest, key, table) | |
112 if table then | |
113 for _, v in pairs(dest) do | |
114 v[key] = {} | |
115 end | |
116 end | |
117 B[key] = setmetatable({}, { | |
118 __index = function(t, k) | |
119 return dest[k][key] | |
120 end, | |
121 __newindex = function(_, k, v) | |
122 print('abstract write ('..key..'):', k) | |
123 dest[k][key] = v | |
124 end, | |
125 __tostring = function() return 'Abstract:'..key..'' end | |
126 }) | |
127 | |
128 | |
129 return B[key] | |
130 end | |
131 | |
132 | |
133 --- localize for speed | |
134 local layers, refs, displays = B.configLayers, B.configLayersRef, B.displays | |
135 | |
136 local ModulesCall = function(func, flag) | |
137 | |
138 local n = 0 | |
139 for i = 1, #moduleStack do | |
140 print('calling level '..i) | |
141 local stackset = moduleStack[i] | |
142 | |
143 for name, module in pairs(stackset) do | |
144 n = n + 1 | |
145 | |
146 | |
147 if module[func] then | |
148 -- nil = pass | |
149 if not flag or module.Conf[flag] then | |
150 if (flag) then | |
151 print(' check', flag, '=', module.Conf[flag]) | |
152 end | |
153 | |
154 print(' ',n..' '..name..'.'..func..'()') | |
155 module[func](module, module.Conf) | |
156 end | |
157 | |
158 end | |
159 end | |
160 end | |
161 end | |
162 | |
163 | |
164 local Enable = function() | |
165 end | |
166 | |
167 --- The things that happen repeatedly | |
168 local Init = function () | |
169 end | |
170 | |
171 | |
172 --- Things that happen immediately upon entering world | |
173 local InitOnce = function() | |
174 print('entering world first time') | |
175 local defaults = B.ConfDefaults | |
176 print('|cFFFFFF00Veneer|r') | |
177 if not VeneerData then | |
178 VeneerData = {} | |
179 for k,v in pairs(defaults) do | |
180 | |
181 | |
182 VeneerData[k] = v | |
183 end | |
184 print('Veneer defaults being used.') | |
185 end | |
186 | |
187 B.Conf = setmetatable(VeneerData, {__index = function(_, k) return defaults[k] end}) | |
188 | |
189 | |
190 | |
191 -- suffix tables | |
192 for name, display in pairs(displays) do | |
193 display.conf = setmetatable({}, { | |
194 __index = function(_, k) | |
195 --print('config check '.. name .. k) | |
196 return B.Conf[name .. k] or B.Conf['BuffButton' .. k] | |
197 end, | |
198 __newindex = function(_, k , v) | |
199 B.Conf[name..k] = v | |
200 end, | |
201 }) | |
202 end | |
203 | |
204 -- To ensure that modules are run in controlled order, walk the dependency list; if the dep shows up | |
205 -- in the loaded manifest, remove the value. If the dep list isn't empty, move that module to the next | |
206 -- layer. | |
207 local loaded = {} | |
208 local stackLevels = #moduleStack | |
209 local i = 1 | |
210 moduleStack[1] = modules | |
211 repeat | |
212 print('setting init level '.. i) | |
213 local queue = moduleStack[i] | |
214 for name, module in pairs(queue) do | |
215 | |
216 if queuedModules[name] and #queuedModules[name] > 0 then | |
217 local p = #queuedModules[name] | |
218 for j = 1, p do | |
219 local dep = queuedModules[name][j] | |
220 | |
221 if loaded[dep] then | |
222 print( ' ' .. dep .. ' OK') | |
223 queuedModules[name][j] = nil | |
224 for k = j, p do | |
225 print(' shift ' .. (k+1) .. ' ('..tostring(queuedModules[name][k+1])..') to ' .. k ..'') | |
226 queuedModules[name][k] = queuedModules[name][k+1] | |
227 end | |
228 end | |
229 end | |
230 | |
231 if #queuedModules[name] == 0 then | |
232 queuedModules[name] = nil | |
233 print(' |cFF00FFFF'.. name ..'|r deps OK') | |
234 loaded[name] = true | |
235 else | |
236 | |
237 print(' |cFFFF8800' .. name ..'|r pending') | |
238 local next = i+1 | |
239 if not moduleStack[next] then | |
240 moduleStack[next] = {} | |
241 end | |
242 stackLevels = next | |
243 moduleStack[next][name] = module | |
244 queue[name] = nil | |
245 end | |
246 | |
247 else | |
248 print(' |cFF00FF00'.. name ..'|r no deps') | |
249 loaded[name] = true | |
250 end | |
251 end | |
252 i = i + 1 | |
253 until i > stackLevels | |
254 | |
255 | |
256 for level, batch in ipairs(moduleStack) do | |
257 print('config level', level) | |
258 for name, module in pairs(batch) do | |
259 if not VeneerData[name] then | |
260 VeneerData[name] = {} | |
261 end | |
262 | |
263 if module.defaults then | |
264 print('setting defaults for module', name) | |
265 --[===[@non-debug@ | |
266 if not VeneerData[name] then | |
267 --@end-non-debug@]===] | |
268 VeneerData[name] = {} | |
269 --[===[@non-debug@ | |
270 end | |
271 --@end-non-debug@]===] | |
272 for k,v in pairs(module.defaults) do | |
273 VeneerData[name][k] = v | |
274 end | |
275 module.Conf = VeneerData[name] | |
276 end | |
277 | |
278 if VeneerData[name].enabled == nil then | |
279 VeneerData[name].enabled = true | |
280 end | |
281 | |
282 end | |
283 end | |
284 | |
285 | |
286 if #checkForConfig >= 1 then | |
287 local queuedFrame = tremove(checkForConfig) | |
288 while queuedFrame do | |
289 B.SetConfigLayers(queuedFrame) | |
290 B.UpdateXMLFrame(queuedFrame) | |
291 queuedFrame = tremove(checkForConfig) | |
292 end | |
293 end | |
294 -- remove from existing | |
295 end | |
296 | |
297 --- Fires an update to all modules | |
298 local lastUpdate | |
299 function B.UpdateAll(...) | |
300 lastUpdate = GetTime() | |
301 ModulesCall('OnUpdate') | |
302 end | |
303 | |
304 B:RegisterEvent('PLAYER_ENTERING_WORLD') | |
305 B:SetScript('OnEvent', function(self, event) | |
306 if event == 'PLAYER_ENTERING_WORLD' then | |
307 if not initOnced then | |
308 InitOnce() | |
309 ModulesCall('OnInitialize') | |
310 initOnced = true | |
311 C_Timer.After(1, function() | |
312 if GetSpecialization() then | |
313 print(GetSpecialization(), 'enabling') | |
314 | |
315 ModulesCall('OnEnable', 'enabled') | |
316 B:SetScript('OnUpdate', nil) | |
317 end | |
318 end) | |
319 end | |
320 end | |
321 | |
322 B.UpdateAll() | |
323 | |
324 if event == 'PLAYER_ENTERING_WORLD' then | |
325 B.UpdateConfigLayers() | |
326 end | |
327 | |
328 end) | |
329 | |
330 --- Modulizer method | |
331 -- | |
332 function B:RegisterModule (name, module, ...) | |
333 if modules[name] then | |
334 print('pulling modules[|cFFFF8800'.. tostring(name) ..'|r]') | |
335 return modules[name] | |
336 end | |
337 | |
338 print('new module |cFF00BBFF'.. tostring(name) ..'|r') | |
339 if module then | |
340 if modules[name] then | |
341 error("Module table for '"..tostring(name).."' already exists.") | |
342 end | |
343 else | |
344 module = CreateFrame('Frame', 'Veneer' .. tostring(name) .. 'Handler', B, 'VeneerHandlerTemplate') | |
345 end | |
346 modules[name] = module | |
347 B[name] = module | |
348 if select('#', ...) >= 1 then | |
349 local numDeps = select('#', ...) | |
350 print(' '..numDeps..' deps detected') | |
351 for i = 1, numDeps do | |
352 local dep = select(i, ...) | |
353 -- means that init/enable funcs are ordered to run after deps do their things | |
354 queuedModules[name] = queuedModules[name] or {} | |
355 tinsert(queuedModules[name], dep) | |
356 print(' needs '..dep) | |
357 end | |
358 end | |
359 return module | |
360 end | |
361 | |
362 | |
363 B.SetConfigLayers = function(frame) | |
364 local print = B.fprint() | |
365 if not frame.config then | |
366 --print(frame:GetName(), 'has no config layers') | |
367 return | |
368 end | |
369 --print('Registering config layers from', frame:GetName()) | |
370 | |
371 for i, subframe in ipairs(frame.config) do | |
372 -- make sure there are no duplicates | |
373 if not refs[subframe] then | |
374 local key = #layers+1 | |
375 layers[key] = subframe | |
376 refs[subframe] = key | |
377 end | |
378 --print(' ', i, subframe:GetName()) | |
379 end | |
380 end | |
381 | |
382 B.RemoveConfigLayers = function(frame) | |
383 | |
384 local print = B.fprint() | |
385 print('|cFFFF0000RemoveConfigLayers', frame:GetName()) | |
386 for i, subframe in pairs(layers) do | |
387 if subframe:GetParent() == frame then | |
388 print('|cFFFF8800 ', subframe:GetParent():GetName(), '|cFFFFFF00', subframe:GetName()) | |
389 layers[i]:Hide() | |
390 layers[i] = nil | |
391 refs[subframe] = nil | |
392 end | |
393 end | |
394 end | |
395 | |
396 B.UpdateConfigLayers = function() | |
397 local print = B.fprint() | |
398 local func = B.Conf.GuidesMode and 'Show' or 'Hide' | |
399 local numAnchors = 0 | |
400 for name, display in pairs(displays) do | |
401 numAnchors = numAnchors + 1 | |
402 display.anchor:EnableMouse(B.Conf.GuidesMode) | |
403 if B.Conf.GuidesMode then | |
404 display.anchor:SetScript('OnUpdate', display.anchor.OnUpdate) | |
405 else | |
406 display.anchor:SetScript('OnUpdate', nil) | |
407 | |
408 for i, anchorButton in ipairs(display.anchor.anchorButton) do | |
409 anchorButton:Hide() | |
410 end | |
411 | |
412 end | |
413 --print(B.Conf.ConfigMode) | |
414 display.anchor:EnableMouse(B.Conf.ConfigMode) | |
415 end | |
416 for id, region in pairs(layers) do | |
417 --print(id, region:GetName(), func) | |
418 region[func](region) | |
419 end | |
420 | |
421 --print('['..func..'] updated', #layers, 'regions,', numAnchors, 'frames') | |
422 end | |
423 | |
424 local XMLFrame_Enable = function(self, value) | |
425 local name = self:GetName() | |
426 local print = B.print('XML') | |
427 | |
428 if not B.Conf[name] then | |
429 B.Conf[name] = { | |
430 enabled = true | |
431 } | |
432 end | |
433 | |
434 print() | |
435 local enabled | |
436 if value == nil then | |
437 if B.Conf[name].enabled == nil then | |
438 print('toggle based on visibility') | |
439 enabled = (not self:IsVisible()) and true or false | |
440 else | |
441 print('toggle a config value =', B.Conf[name].enabled) | |
442 enabled = B.Conf[name].enabled | |
443 end | |
444 | |
445 enabled = (enabled ~= true) and true or false | |
446 else | |
447 print('use argument value', value) | |
448 enabled = value | |
449 end | |
450 | |
451 print('arg =', value, 'conf =', B.Conf[name].enabled, 'result=', enabled) | |
452 | |
453 B.Conf[name].enabled = enabled | |
454 | |
455 local stateFunc = enabled and 'Show' or 'Hide' | |
456 local eventFunc = enabled and 'OnToggle' or 'OnToggle' | |
457 --- taggled layers | |
458 if self.toggled then | |
459 for i, region in pairs(self.toggled) do | |
460 region[stateFunc](region) | |
461 end | |
462 end | |
463 --- toggle action | |
464 if self.OnToggle then | |
465 self:OnToggle(B.Conf[name].enabled) | |
466 end | |
467 --- do enable | |
468 if B.Conf[name].enabled then | |
469 if self.OnEnable then | |
470 self:OnEnable() | |
471 end | |
472 else | |
473 if self.OnDisable then | |
474 self:OnDisable() | |
475 end | |
476 end | |
477 end | |
478 --- Generic handlers for keeping track of XML-defined frames | |
479 local print = B.print('XML') | |
480 B.prototypes = {} | |
481 B.prototypes.OnDragStart = function(self) | |
482 local print = B.print('XML') | |
483 self.xA = self:GetLeft() | |
484 self.yA = self:GetBottom() | |
485 self.anchorTo, self.relativeTo, self.relativePoint, self.x, self.y = self:GetPoint(1) | |
486 print('acquire anchor', self:GetPoint(1)) | |
487 print(self:GetName(), 'start moving ('..self.x..', '..self.y..')') | |
488 self:StartMoving() | |
489 end | |
490 | |
491 B.prototypes.OnDragStop = function(self) | |
492 local print = B.print('XML') | |
493 local name = self:GetName() | |
494 print(name, 'stop moving ('..self:GetLeft()..', '..self:GetBottom()..')') | |
495 local xB = self:GetLeft() - self.xA | |
496 local yB = self:GetBottom() - self.yA | |
497 print('storing anchor point', self.anchorTo, self.relativePoint, self.x + xB, self.y + yB) | |
498 | |
499 self:StopMovingOrSizing() | |
500 B.Conf[name].position = {self.anchorTo, self.relativePoint, self.x + xB, self.y + yB} | |
501 B.UpdateXMLFrame(self) | |
502 end | |
503 | |
504 | |
505 B.RegisterModuleFrame = function(self, moduleName) | |
506 local print = B.print('XML') | |
507 local name = self:GetName() | |
508 tinsert(checkForConfig, self) | |
509 self.Enable = XMLFrame_Enable | |
510 self.moduleName = moduleName | |
511 print('|cFF00FF00XML stuff related to '.. tostring(moduleName) .. ':', self:GetName()) | |
512 ------------------------------------------------------------------------------------------ | |
513 if not B[name] then | |
514 return | |
515 end | |
516 | |
517 local scriptTypes = {'OnUpdate', 'OnEvent', 'OnDragStart', 'OnDragStop'} | |
518 for script in next(scriptTypes) do | |
519 if B[name][script] then | |
520 self:SetScript(script, B[name][script]) | |
521 end | |
522 end | |
523 | |
524 end | |
525 | |
526 B.UpdateXMLFrame = function(self) | |
527 local print = B.print('XML') | |
528 | |
529 local name = self:GetName() | |
530 | |
531 | |
532 if self.drag then | |
533 self:RegisterForDrag('LeftButton') | |
534 self:SetScript('OnDragStart', XMLFrame_OnDragStart) | |
535 if self.OnDragStop then | |
536 self:SetScript('OnDragStop', function(self, ...) | |
537 print('|cFFFF0088end of dragging') | |
538 self:OnDragStop(self, ...) | |
539 XMLFrame_OnDragStop(self, ...) | |
540 end) | |
541 else | |
542 self:SetScript('OnDragStop', XMLFrame_OnDragStop) | |
543 end | |
544 else | |
545 self:EnableMouse(false) | |
546 end | |
547 | |
548 if not B.Conf[name] then | |
549 B.Conf[name] = { | |
550 enabled = self.enabled, | |
551 } | |
552 end | |
553 local c = B.Conf[name] | |
554 | |
555 if not c.position then | |
556 local anchor, _, point, x, y = self:GetPoint(1) | |
557 print('seeding default position', anchor, point, x, y) | |
558 c.position = {anchor, point, x, y} | |
559 else | |
560 | |
561 print('restoring frame position', unpack(c.position)) | |
562 self:ClearAllPoints() | |
563 local anchorTo, relativePoint, x, y = unpack(c.position) | |
564 self:SetPoint(anchorTo, UIParent, relativePoint, x, y) | |
565 end | |
566 self:Enable(c.enabled) | |
567 | |
568 | |
569 end |