Mercurial > wow > devian
comparison Devian.lua @ 98:33bc8baba858
start of a lot of v3 groundwork based on better knowledge of the addon interface:
- use of mixin as a lexical center for generated frames
- removal of unfinished segments
author | Nenue |
---|---|
date | Wed, 26 Oct 2016 10:17:43 -0400 |
parents | f6fae1a4c66c |
children | 7d94df3804a7 |
comparison
equal
deleted
inserted
replaced
97:34131d11e61b | 98:33bc8baba858 |
---|---|
9 DEVIAN_PNAME = 'Dvn' | 9 DEVIAN_PNAME = 'Dvn' |
10 DEVIAN_PID = 0 | 10 DEVIAN_PID = 0 |
11 | 11 |
12 local ADDON, D = ... | 12 local ADDON, D = ... |
13 local MAJOR, MINOR = 'Devian-2.0', 'r@project-revision@' | 13 local MAJOR, MINOR = 'Devian-2.0', 'r@project-revision@' |
14 local D = LibStub("AceAddon-3.0"):NewAddon(D, "Devian", "AceConsole-3.0", "AceEvent-3.0") | 14 local D_INITIALIZED |
15 local L = D.L | 15 local next = next |
16 Devian = D | |
17 local sub, GetTime, print, _G = string.sub, GetTime, print, _G | 16 local sub, GetTime, print, _G = string.sub, GetTime, print, _G |
18 local format, setmetatable, getprinthandler, setprinthandler = string.format, setmetatable, getprinthandler, setprinthandler | 17 local format, setmetatable, getprinthandler, setprinthandler = string.format, setmetatable, getprinthandler, setprinthandler |
19 local tinsert, tremove, rawset = tinsert, tremove, rawset | 18 local tinsert, tremove, rawset = tinsert, tremove, rawset |
20 local currentProfile | 19 local currentProfile |
21 local playerName = UnitName("player") | 20 local playerName = UnitName("player") |
22 local playerRealm = playerName .. '-' .. GetRealmName() | 21 local playerRealm = playerName .. '-' .. GetRealmName() |
23 local num_dock_tabs = 0 | 22 local num_dock_tabs = 0 |
24 local charStates ={} | 23 local charStates ={} |
25 | 24 |
25 local registeredTags = {} | |
26 | |
27 | |
28 DevianCore = {} | |
29 | |
30 function DevianCore:OnLoad () | |
31 self:RegisterEvent('ADDON_LOADED') | |
32 self:RegisterEvent('PLAYER_LOGIN') | |
33 self:SetShown(true) | |
34 end | |
35 | |
36 function DevianCore:OnEvent(event, arg) | |
37 if event == 'ADDON_LOADED' or event == 'PLAYER_LOGIN' then | |
38 --print(event, arg, DevianDB) | |
39 if (arg == 'Devian') and not D_INITIALIZED then | |
40 D_INITIALIZED = true | |
41 self:Initialize() | |
42 self:UnregisterAllEvents() | |
43 end | |
44 end | |
45 end | |
46 | |
26 DevianLoadMessage = setmetatable({}, { | 47 DevianLoadMessage = setmetatable({}, { |
27 __call = function(t, msg) | 48 __call = function(t, msg) |
28 rawset(t, #t+1, msg) | 49 rawset(t, #t+1, msg) |
29 end, | 50 end, |
30 __index = function(t) | 51 __index = function(t) |
35 --@debug@ | 56 --@debug@ |
36 D.debugmode = true | 57 D.debugmode = true |
37 --@end-debug@ | 58 --@end-debug@ |
38 D.print = function(...) | 59 D.print = function(...) |
39 if currentProfile and not currentProfile.workspace then | 60 if currentProfile and not currentProfile.workspace then |
40 return | 61 return nop |
41 end | 62 end |
42 | 63 |
43 if D.debugmode then | 64 if D.debugmode then |
44 return print('Dvn', ...) | 65 return print('Dvn', ...) |
45 else | 66 else |
48 end | 69 end |
49 local print = D.print | 70 local print = D.print |
50 | 71 |
51 D.L = setmetatable({}, { | 72 D.L = setmetatable({}, { |
52 __index= function(t,k) | 73 __index= function(t,k) |
53 return k | 74 return tostring(k) |
54 end, | 75 end, |
55 __call = function(t,k,...) | 76 __call = function(t,k,...) |
56 return format((t[k] or k) , ...) | 77 return format((t[k]) , ...) |
57 end | 78 end |
58 }) | 79 }) |
59 D:SetDefaultModuleState(false) | |
60 D.oldprint = getprinthandler() | 80 D.oldprint = getprinthandler() |
61 if not _G.oldprint then _G.oldprint = D.oldprint end | 81 if not _G.oldprint then _G.oldprint = D.oldprint end |
62 | 82 |
63 local pairs, tostring, tonumber, ipairs, type = pairs, tostring, tonumber, ipairs, type | 83 local pairs, tostring, tonumber, ipairs, type = pairs, tostring, tonumber, ipairs, type |
64 local max, rand, format, print = max, math.random, string.format, print | 84 local max, rand, format, print = max, math.random, string.format, print |
65 local insert, wipe, concat = table.insert, table.wipe, table.concat | 85 local insert, wipe, concat = table.insert, table.wipe, table.concat |
66 local select, unpack = select, unpack | 86 local select, unpack = select, unpack |
67 local GetNumAddOns, GetAddOnInfo, GetAddOnEnableState, EnableAddOn = GetNumAddOns, GetAddOnInfo, GetAddOnEnableState, EnableAddOn | 87 local GetNumAddOns, GetAddOnInfo, GetAddOnEnableState, EnableAddOn = GetNumAddOns, GetAddOnInfo, GetAddOnEnableState, EnableAddOn |
68 local UnitName, DisableAddOn = UnitName, DisableAddOn | 88 local UnitName, DisableAddOn = UnitName, DisableAddOn |
69 | 89 |
70 local db | 90 local db, L |
71 local defaults = { | 91 local defaults = { |
72 global = {{}, {}}, | 92 global = {{}, {}}, |
73 default_channel = { | 93 default_channel = { |
74 signature = 'Main', | 94 signature = 'Main', |
75 x = 100, y = 800, | 95 x = 100, y = -200, |
76 height = 500, width = 600, | 96 height = 500, width = 600, |
77 enabled = true}, | 97 enabled = true}, |
78 current_profile = 1, | 98 current_profile = 1, |
79 main_profile = 1, | 99 main_profile = 1, |
80 last_profile = 1, | 100 last_profile = 1, |
147 enabled = true, -- allow enabled consoles to appear | 167 enabled = true, -- allow enabled consoles to appear |
148 channels = { | 168 channels = { |
149 { | 169 { |
150 index = 1, | 170 index = 1, |
151 signature = 'Main', | 171 signature = 'Main', |
152 x = 100, y = 800, | 172 x = 100, y = -200, |
153 height = 500, width = 600, | 173 height = 500, width = 600, |
154 enabled = true | 174 enabled = true |
155 } | 175 } |
156 }, | 176 }, |
157 loadouts = {}, | 177 loadouts = {}, |
182 end | 202 end |
183 end | 203 end |
184 end | 204 end |
185 end | 205 end |
186 | 206 |
207 D.FixProfile = function(forced) | |
208 | |
209 local numChannels = 0 | |
210 local minChannel = 400 | |
211 local sortedChannels = {} | |
212 local sortedTags = {} | |
213 local maxChannel = 0 | |
214 for k,v in pairs(currentProfile.channels) do | |
215 numChannels = numChannels + 1 | |
216 maxChannel = max(tonumber(k), maxChannel) | |
217 minChannel = min(tonumber(k), minChannel) | |
218 tinsert(sortedChannels, v) | |
219 end | |
220 if (maxChannel > numChannels) or forced then | |
221 oldprint('fixing channels data') | |
222 table.sort(sortedChannels, function(a,b) | |
223 return (b.index > a.index) | |
224 end) | |
225 for i, info in ipairs(sortedChannels) do | |
226 for tag, tagSet in pairs(currentProfile.tags) do | |
227 for _, index in pairs(tagSet) do | |
228 if index == info.index then | |
229 sortedTags[tag] = sortedTags[tag] or {} | |
230 sortedTags[tag][i] = i | |
231 end | |
232 end | |
233 end | |
234 | |
235 info.index = i | |
236 end | |
237 currentProfile.channels = sortedChannels | |
238 currentProfile.tags = sortedTags | |
239 else | |
240 minChannel = 2 | |
241 end | |
242 currentProfile.lastUpdateFix = MINOR | |
243 end | |
244 | |
187 D.Profile = function (id, name) | 245 D.Profile = function (id, name) |
188 | 246 |
189 if name and not id and db.profilesName[name] then | 247 if name and not id and db.profilesName[name] then |
190 id = db.profilesName[name] | 248 id = db.profilesName[name] |
191 print('ID located by name, |cFF00FF00'..name..'|r is |cFFFFFF00'.. id..'|r') | 249 print('ID located by name, |cFF00FF00'..name..'|r is |cFFFFFF00'.. id..'|r') |
227 currentProfile.char[playerRealm] = currentProfile.char[playerRealm] or {} | 285 currentProfile.char[playerRealm] = currentProfile.char[playerRealm] or {} |
228 if currentProfile.workspace then | 286 if currentProfile.workspace then |
229 DEVIAN_WORKSPACE = true | 287 DEVIAN_WORKSPACE = true |
230 DEVIAN_PNAME = currentProfile.name | 288 DEVIAN_PNAME = currentProfile.name |
231 DEVIAN_PID = id | 289 DEVIAN_PID = id |
290 print('setting phandler') | |
232 setprinthandler(D.Message) | 291 setprinthandler(D.Message) |
233 else | 292 else |
234 DEVIAN_WORKSPACE = false | 293 DEVIAN_WORKSPACE = false |
235 DEVIAN_PNAME = nil | 294 DEVIAN_PNAME = nil |
236 print = nop | 295 print = nop |
237 end | 296 end |
238 DEVIAN_PID =id | 297 DEVIAN_PID =id |
298 | |
299 | |
300 -- Attempt to fix bad data | |
301 --@debug@ | |
302 MINOR = 70100 | |
303 --@end-debug@ | |
304 if (currentProfile.lastUpdateFix or 0) < MINOR then | |
305 D.FixProfile(true) | |
306 end | |
307 | |
239 | 308 |
240 D.unlisted = currentProfile.unlisted | 309 D.unlisted = currentProfile.unlisted |
241 D.channels = currentProfile.channels | 310 D.channels = currentProfile.channels |
242 D.tags = currentProfile.tags | 311 D.tags = currentProfile.tags |
243 D.channelinfo = currentProfile.channels | 312 D.channelinfo = currentProfile.channels |
248 D.sig = {} | 317 D.sig = {} |
249 D.sigID = {} | 318 D.sigID = {} |
250 D.IDsig = {} | 319 D.IDsig = {} |
251 D.dock = _G.DevianDock | 320 D.dock = _G.DevianDock |
252 D.dock.buttons = D.dock.buttons or {} | 321 D.dock.buttons = D.dock.buttons or {} |
322 | |
323 | |
253 | 324 |
254 return id, name | 325 return id, name |
255 end | 326 end |
256 | 327 |
257 local targetGlobal, targetChar | 328 local targetGlobal, targetChar |
448 if globalState ~= 1 then | 519 if globalState ~= 1 then |
449 charStates[name] = globalState | 520 charStates[name] = globalState |
450 end | 521 end |
451 end | 522 end |
452 | 523 |
524 D.UpdateTags = function() | |
525 | |
526 wipe(registeredTags) | |
527 for tag, tagSet in pairs(currentProfile.tags) do | |
528 registeredTags[tag] = registeredTags[tag] or {} | |
529 for _, id in pairs(tagSet) do | |
530 if D.console[id] then | |
531 tinsert(registeredTags[tag], D.console[id]) | |
532 end | |
533 end | |
534 end | |
535 end | |
536 | |
453 D.Tag = function(self, tag, dest) | 537 D.Tag = function(self, tag, dest) |
454 local sig | 538 local sig |
455 if tag ~= nil and dest ~= nil then | 539 if tag ~= nil and dest ~= nil then |
456 --@debug@ | 540 --@debug@ |
457 --print(tag, dest) | 541 --print(tag, dest) |
471 --print('2 tag,dest,sig', tag, dest, sig)--@end-debug@ | 555 --print('2 tag,dest,sig', tag, dest, sig)--@end-debug@ |
472 | 556 |
473 -- make a new channel? | 557 -- make a new channel? |
474 local channel | 558 local channel |
475 if not currentProfile.channels[dest] then | 559 if not currentProfile.channels[dest] then |
476 dest = D.max_channel + 1 | 560 dest = #D.channels + 1 |
477 D:Print(L('New channel created', sig and (dest..':'..sig) or dest )) | 561 D:Print(L('New channel created', sig and (dest..':'..sig) or dest )) |
478 channel = D:SetChannel(sig or tag,dest) | 562 channel = D:GetOrCreateChannel(dest, tag) |
479 else | 563 else |
480 channel = D.channels[dest] | 564 channel = currentProfile.channels[dest] |
481 end | 565 end |
482 --@debug@ | 566 --@debug@ |
483 --print('3 tag,dest,channel.sig=',tag, dest, channel.signature)--@end-debug@ | 567 --print('3 tag,dest,channel.sig=',tag, dest, channel.signature)--@end-debug@ |
484 | 568 |
485 if not currentProfile.tags[tag] then -- no tag table? | 569 if not currentProfile.tags[tag] then -- no tag table? |
486 currentProfile.tags[tag] = {} | 570 currentProfile.tags[tag] = {} |
487 end | 571 end |
488 | 572 |
489 if currentProfile.tags[tag][dest] then -- is tag set? | 573 if currentProfile.tags[tag][dest] then -- is tag set? |
490 currentProfile.tags[tag][dest] = nil | 574 currentProfile.tags[tag][dest] = nil |
491 D:Print(L('Tag removed from channel', tag, currentProfile.channels[dest].index, currentProfile.channels[dest].signature)) | 575 D:Print(L('Tag removed from channel', tag, currentProfile.channels[dest].index, currentProfile.channels[dest].signature)) |
492 else | 576 else |
493 currentProfile.tags[tag][dest] = dest | 577 currentProfile.tags[tag][dest] = dest |
494 D:Print(L('Tag added to channel', tag, currentProfile.channels[dest].index, currentProfile.channels[dest].signature)) | 578 D:Print(L('Tag added to channel', tag, channel.index, channel.signature)) |
495 end | 579 end |
496 D:UpdateDock() | 580 D.UpdateTags() |
581 DevianDock:Update() | |
497 else | 582 else |
498 D:Print(L['Command tag help']) | 583 D:Print(L['Command tag help']) |
499 end | 584 end |
500 end | 585 end |
501 | 586 |
545 --- Creates a Devian-style output. | 630 --- Creates a Devian-style output. |
546 -- The first argument describes the channel to output on, and the remaining arguments are concatenated in a manner similar to default print() | 631 -- The first argument describes the channel to output on, and the remaining arguments are concatenated in a manner similar to default print() |
547 -- This becomes the print handler when development mode is active. The original print() function is assigned to oldprint(). | 632 -- This becomes the print handler when development mode is active. The original print() function is assigned to oldprint(). |
548 -- @param Tag, signature, or numeric index of the channel to output on. Defaults to primary channel. | 633 -- @param Tag, signature, or numeric index of the channel to output on. Defaults to primary channel. |
549 -- @param ... Output contents. | 634 -- @param ... Output contents. |
550 | 635 local default_sendq = {} |
551 function D.Message(prefix, ...) | 636 function D.Message(prefix, ...) |
552 if not currentProfile.workspace then | 637 if not currentProfile.workspace then |
553 return D.oldprint(prefix, ...) | 638 return D.oldprint(prefix, ...) |
554 end | 639 end |
640 local print = D.oldprint | |
555 prefix = tostring(prefix) | 641 prefix = tostring(prefix) |
556 if prefix == nil then | 642 if prefix == nil then |
557 prefix = 'nil*' | 643 prefix = 'nil*' |
558 end | 644 end |
559 | 645 |
560 local sendq = {} | 646 local sendq = default_sendq |
561 local tag, id, tagged | 647 local tag, id, tagged |
562 local byName = true | 648 local byName = true |
563 if D.tags[prefix] then | 649 |
564 for _, id in pairs(D.tags[prefix]) do | 650 if registeredTags[prefix] then |
565 if D.console[id] then | 651 sendq = registeredTags[prefix] |
566 sendq[id] = D.console[id] | 652 else |
567 tagged = true | 653 if D.sig[prefix] then |
568 end | 654 sendq[D.sig[prefix].index] = D.sig[prefix] |
569 end | 655 elseif not tagged then |
570 end | 656 sendq[1] = D.console[D.primary_channel] |
571 | 657 end |
572 if D.sig[prefix] then | 658 end |
573 sendq[D.sig[prefix].index] = D.sig[prefix] | 659 |
574 elseif D.console[prefix] then | 660 |
575 sendq[D.console[prefix]] = D.console[prefix] | |
576 elseif not tagged then | |
577 sendq[D.primary_channel] = D.console[D.primary_channel] | |
578 end | |
579 | 661 |
580 -- color me timbers | 662 -- color me timbers |
581 local pcolor | 663 local pcolor |
582 if (not db.tagcolor[prefix]) and byName then | 664 if (not db.tagcolor[prefix]) and byName then |
583 -- numbers, use white | 665 -- numbers, use white |
623 local message = concat(buffer, ' ') | 705 local message = concat(buffer, ' ') |
624 for id, channel in pairs(sendq) do | 706 for id, channel in pairs(sendq) do |
625 if channel.width < 250 then | 707 if channel.width < 250 then |
626 prefix = sub(prefix, 0,2) | 708 prefix = sub(prefix, 0,2) |
627 end | 709 end |
628 --currentProfile.last_channel = channel.index | 710 channel.out:AddMessage('|cFF'.. pcolor..prefix ..'|r ' .. message, 0.8, 0.8, 0.8) |
629 channel.out:AddMessage('|cFF'.. pcolor..prefix ..'|r ' .. message, 0.8, 0.8, 0.8, nil, nil, prefix, GetTime()) | 711 if channel.Dock and not channel.Dock.newMessage then |
630 if not D.dock.usedButtons[id].newMessage then | 712 channel.Dock.newMessage = true |
631 D.dock.usedButtons[id].newMessage = true | 713 channel.Dock.caption.pulse:Play() |
632 D.dock.usedButtons[id].caption.pulse:Play() | 714 channel.Dock:Update() |
633 D.dock.usedButtons[id]:Update() | |
634 end | 715 end |
635 end | 716 end |
636 wipe(buffer) | 717 wipe(buffer) |
637 end | 718 end |
638 | 719 |
680 function D.ConsoleCommand (cmd) | 761 function D.ConsoleCommand (cmd) |
681 D:Console_Toggle(cmd) | 762 D:Console_Toggle(cmd) |
682 end | 763 end |
683 | 764 |
684 | 765 |
685 function D:OnInitialize() | 766 function DevianCore:Initialize() |
686 L = D.L | 767 L = D.L |
687 | 768 |
688 -- pull defaults | 769 -- pull defaults |
689 if not _G.DevianDB then | 770 if not DevianDB then |
690 _G.DevianDB = defaults | 771 DevianDB = defaults |
691 end | 772 end |
773 D.db = _G.DevianDB | |
692 db = _G.DevianDB | 774 db = _G.DevianDB |
693 self.db = db | |
694 | 775 |
695 --- | 776 --- |
696 if #_G.DevianLoadMessage >= 1 then | 777 if #_G.DevianLoadMessage >= 1 then |
697 for i, msg in ipairs(_G.DevianLoadMessage) do | 778 for i, msg in ipairs(_G.DevianLoadMessage) do |
698 D:Print(msg) | 779 D:Print(msg) |
733 D:Print('Default channel: |cFFFFFF00'..currentProfile.default_channel..'|r: |cFF00FFFF'.. D.channels[currentProfile.default_channel].signature..'|r') | 814 D:Print('Default channel: |cFFFFFF00'..currentProfile.default_channel..'|r: |cFF00FFFF'.. D.channels[currentProfile.default_channel].signature..'|r') |
734 end | 815 end |
735 end | 816 end |
736 | 817 |
737 | 818 |
738 for i, cinfo in pairs(D.channels) do | 819 |
739 i = tonumber(i) | 820 for index, cinfo in ipairs(D.channels) do |
821 --oldprint(index, cinfo.signature) | |
740 if not D.primary_channel then | 822 if not D.primary_channel then |
741 D.primary_channel = i | 823 D.primary_channel = index |
742 end | 824 end |
743 D:SetChannel(cinfo, i) | 825 D:GetOrCreateChannel(index) |
744 D.num_channels = D.num_channels + 1 | 826 D.num_channels = #D.channels |
745 end | 827 end |
746 D.primary_channel = D.primary_channel or 1 | 828 D.primary_channel = D.primary_channel or 1 |
747 | |
748 D.max_channel = max(D.max_channel, currentProfile.max_channel) | 829 D.max_channel = max(D.max_channel, currentProfile.max_channel) |
749 if currentProfile.max_channel < D.max_channel then | 830 if currentProfile.max_channel < D.max_channel then |
750 for i = currentProfile.max_channel, D.max_channel do | 831 for i = currentProfile.max_channel, D.max_channel do |
751 D.console[i]:Hide() | 832 D.console[i]:Hide() |
752 end | 833 end |
753 end | 834 end |
835 | |
836 D.UpdateTags() | |
754 | 837 |
755 if currentProfile.workspace then | 838 if currentProfile.workspace then |
756 if D.console[currentProfile.current_channel] then | 839 if D.console[currentProfile.current_channel] then |
757 --print('bringing', D.console[currentProfile.current_channel].signature, 'to the front') | 840 --print('bringing', D.console[currentProfile.current_channel].signature, 'to the front') |
758 D.console[currentProfile.current_channel]:ToFront() | 841 D.console[currentProfile.current_channel]:ToFront() |
759 -- bring the current channel to the front | 842 -- bring the current channel to the front |
760 end | 843 end |
761 _G.DevianDock:Show() | 844 DevianDock:Update() |
762 D:UpdateDock() | 845 end |
763 end | 846 |
764 end | 847 print('devian') |
765 | 848 end |
849 | |
850 function D:Print (...) | |
851 local msg = '|cFF00FF44Devian|r:' | |
852 for i = 1, select('#', ...) do | |
853 msg = msg .. ' ' .. tostring(select(i, ...)) | |
854 end | |
855 DEFAULT_CHAT_FRAME:AddMessage(msg) | |
856 end | |
857 | |
858 function D:GetActiveChannel() | |
859 return D.console[currentProfile.current_channel] | |
860 end | |
861 | |
862 function D:GetOrCreateChannel(id, name) | |
863 local info = D.channels[id] | |
864 local frame = D.console[id] | |
865 if not frame then | |
866 | |
867 --print('new frame') | |
868 frame = CreateFrame('Frame', 'DevianConsole'..id, Devian, 'DevianConsoleTemplate') | |
869 frame:SetID(id) | |
870 D.console[id] = frame | |
871 end | |
872 if not info then | |
873 --print('new channel') | |
874 info = { | |
875 } | |
876 D.DeepCopy(defaults.default_channel, info) | |
877 info.index = id | |
878 info.signature = name | |
879 D.channels[id] = info | |
880 end | |
881 | |
882 | |
883 frame:Setup(info) | |
884 return frame | |
885 end |