Quantcast Toggling modules with proxy table - WoWInterface
Thread Tools Display Modes
02-14-18, 10:59 PM   #1
Layback_
An Onyxian Warder
Join Date: Feb 2016
Posts: 356
Toggling modules with proxy table

So, as a part of my small project I'm working on a functionality to toggle modules depending on player's current specialization and here's a brief draft of what I've done so far:

Lua Code:
  1. local specList = {}; -- Proxy
  2. local _specList = {};
  3.  
  4. local f = CreateFrame("Frame");
  5. f:RegisterEvent("PLAYER_LOGIN");
  6. f:SetScript("OnEvent", function(self, event, ...)
  7.     if event == "PLAYER_LOGIN" then
  8.         local currentSpecIndex = GetSpecialization();
  9.  
  10.         for index = 1, GetNumSpecializations() do
  11.             local id = GetSpecializationInfo(index);
  12.  
  13.             _specList[id] = {};
  14.  
  15.             specList[id] = setmetatable({
  16.                 __parent = specList, -- to access parent table
  17.                 _specList = _specList,
  18.             },
  19.             {
  20.                 __index = function(t, k)
  21.                     local specList = t.__parent;
  22.                     local _specList = t._specList;
  23.  
  24.                     for sK, sV in pairs(specList) do
  25.                         if t == sV then
  26.                             for _sK, _sV in pairs(_specList) do
  27.                                 if sK == _sK then
  28.                                     return _sV[k];
  29.                                 end
  30.                             end
  31.                         end
  32.                     end
  33.                 end,
  34.                 __newindex = function(t, k, v)
  35.                     if k == "enabled" and v then
  36.                         local specList = t.__parent;
  37.                         local _specList = t._specList;
  38.  
  39.                         for sK, sV in pairs(specList) do
  40.                             if t == sV then
  41.                                 for _sK, _sV in pairs(_specList) do
  42.                                     _sV.enabled = sK == _sK;
  43.                                 end
  44.  
  45.                                 break;
  46.                             end
  47.                         end
  48.                     end
  49.                 end,
  50.             });
  51.         end
  52.  
  53.         local id = GetSpecializationInfo(currentSpecIndex);
  54.         specList[id].enabled = true;
  55.  
  56.         self:RegisterEvent("ACTIVE_TALENT_GROUP_CHANGED");
  57.  
  58.         self:UnregisterEvent("PLAYER_LOGIN");
  59.     elseif event == "ACTIVE_TALENT_GROUP_CHANGED" then
  60.         local id = GetSpecializationInfo(GetSpecialization());
  61.         specList[id].enabled = true;
  62.     end
  63. end);

It's working perfectly well as I expected, BUT all those nasty for loops & if statements look so messy and I'm pretty sure I would forget what the hxxk I've done here in the close future.
(I'll be changing the variable names and leave comments, tho...)

It would be grateful if someone could come up with better ideas.

Thank you!

Last edited by Layback_ : 02-14-18 at 11:21 PM.
  Reply With Quote
02-14-18, 11:36 PM   #2
Ammako
A Cobalt Mageweaver
 
Ammako's Avatar
AddOn Author - Click to view addons
Join Date: Jun 2016
Posts: 248
Couldn't tell for your actual question (and also I don't know what your addon is meant to actually do), but I do notice something right away:

On spec change, you enable the list (module?) for that spec, but don't disable the others (unless there's some dark magic at work in your code that I can't work out.) So if you changed specs multiple times, you'd just end up having everything enabled, rather than toggling according to spec changes.

Might be worth seeing if that's not causing issues, and if it's not, then it can probably be left as-is. I just thought I'd mention it.
__________________
  Reply With Quote
02-14-18, 11:42 PM   #3
Phanx
Cat.
 
Phanx's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2006
Posts: 5,617
I already don't know what the heck you've done there.

I'd do something like this very light and totally untested system that uses AceDB and replicates the basic features of AceAddon and AceEvent, plus some specialized logic to automatically toggle modules on and off based on spec:

Lua Code:
  1. -- create addon object:
  2. local MyAddon = CreateFrame("Frame", "MyAddon")
  3.  
  4. -- create table to use as a module registry:
  5. MyAddon.modules = {}
  6.  
  7. -- set up AceEvent-style event handling:
  8. local function eventHandler(self, event, ...) return self[event](self, ...) end
  9. MyAddon:SetScript("OnEvent", eventHandler)
  10. MyAddon:RegisterEvent("PLAYER_LOGIN")
  11.  
  12. -- add module creation:
  13. function MyAddon:NewModule(name, defaults)
  14.     -- make each module its own object with its own event handling:
  15.     local module = CreateFrame("Frame")
  16.     module:SetScript("OnEvent", eventHandler)
  17.  
  18.     if defaults then
  19.         if self.db then
  20.             -- for modules registered after login:
  21.             module.db = self.db:RegisterNamespace(name, defaults)
  22.         else
  23.             -- for modules registered before/during login,
  24.             -- the core db doesn't exist yet, so hold onto it:
  25.             self.pending = self.pending or {}
  26.             self.pending[name] = defaults
  27.         end
  28.     end
  29.  
  30.     -- add it to the registry:
  31.     self.modules[name] = module
  32.  
  33.     -- and pass back a reference to the object:
  34.     return module
  35. end
  36.  
  37. function MyAddon:GetModule(name)
  38.     return self.modules[name]
  39. end
  40.  
  41. -- basically OnInitialize:
  42. function MyAddon:PLAYER_LOGIN()
  43.     -- register the core addon db here:
  44.     local defaults = {
  45.         profile = {
  46.             cats = true,
  47.             dogs = false,
  48.         }
  49.     }
  50.     self.db = LibStub("AceDB-3.0"):New("MyAddonDB", defaults, true)
  51.  
  52.     -- deal with modules registered before/during login:
  53.     if self.pending then
  54.         for name, defaults in pairs(self.pending) do
  55.             local module = self.modules[name]
  56.             module.db = self.db:RegisterNamespace(name, defaults)
  57.         end
  58.         self.pending = nil
  59.     end
  60.  
  61.     -- register your main logic event:
  62.     self:RegisterEvent("ACTIVE_TALENT_GROUP_CHANGED")
  63.     self:ACTIVE_TALENT_GROUP_CHANGED()
  64. end
  65.  
  66. -- handle your main logic event:
  67. function MyAddon:ACTIVE_TALENT_GROUP_CHANGED()
  68.     local id = GetSpecializationInfo(GetSpecialization())
  69.     -- go through all the registered modules:
  70.     for name, module in pairs(self.modules) do
  71.         -- and enable or disable them according to whether they match the current spec:
  72.         if module.specID == id then
  73.             module.enabled = true
  74.             module:Enable()
  75.         else
  76.             module:Disable()
  77.             module.enabled = false
  78.         end
  79.     end
  80. end

And then in each module:
Lua Code:
  1. -- create a new module with some default profile settings:
  2. local DruidCatModule = MyAddon:NewModule("DruidCat", {
  3.     profile = {
  4.         fluffy = true,
  5.     }
  6. })
  7.  
  8. -- give it a specID so the core can figure out when to toggle it:
  9. DruidCatModule.specID = 12345 -- note: not the real spell ID!
  10.  
  11. -- and an Enable method the core can call to turn it on:
  12. function DruidCatModule:Enable()
  13.     -- register for events, create frames if they don't exist yet, show frames
  14.  
  15.     -- self.db gives you the module's specific db
  16.  
  17.     -- register an event just like you would in the core or with AceEvent:
  18.     self:RegisterEvent("EXAMPLE_EVENT")
  19. end
  20.  
  21. -- and a Disable method the core can call to turn it off:
  22. function DruidCatModule:Disable()
  23.     -- unregister events, hide frames
  24.  
  25.     self:UnregisterEvent("EXAMPLE_EVENT")
  26. end
  27.  
  28. -- and handle an event like so:
  29. function DruidCatModule:EXAMPLE_EVENT(fakeArg)
  30.     print("This will never happen.")
  31. end
__________________
Author/maintainer of Grid, PhanxChat, oUF_Phanx, and many more.
Troubleshoot an addonTurn any code into an addonMore addon resources
Need help with your code? Post all of your actual code! Attach or paste your files.
Please don’t PM me about addon bugs or code questions. Post a comment or forum thread instead!

Last edited by Phanx : 02-15-18 at 12:06 AM.
  Reply With Quote
02-14-18, 11:57 PM   #4
Layback_
An Onyxian Warder
Join Date: Feb 2016
Posts: 356
Originally Posted by Ammako View Post
Couldn't tell for your actual question (and also I don't know what your addon is meant to actually do), but I do notice something right away:

On spec change, you enable the list (module?) for that spec, but don't disable the others (unless there's some dark magic at work in your code that I can't work out.) So if you changed specs multiple times, you'd just end up having everything enabled, rather than toggling according to spec changes.

Might be worth seeing if that's not causing issues, and if it's not, then it can probably be left as-is. I just thought I'd mention it.
Sorry for lack of explanation

So, it's like how a group of radio buttons would behave.

Let's say I'm a druid and there are 4 different specs. Switching myself to feral from boomy would enable module for feral, but disable all other specs' module (guardian, resto and boomy). This is what I've been working
  Reply With Quote
02-15-18, 12:07 AM   #5
Phanx
Cat.
 
Phanx's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2006
Posts: 5,617
I see you've already replied to the thread, so be aware I've edited the code in my last post several times in the meantime.
__________________
Author/maintainer of Grid, PhanxChat, oUF_Phanx, and many more.
Troubleshoot an addonTurn any code into an addonMore addon resources
Need help with your code? Post all of your actual code! Attach or paste your files.
Please don’t PM me about addon bugs or code questions. Post a comment or forum thread instead!
  Reply With Quote
02-15-18, 12:12 AM   #6
Layback_
An Onyxian Warder
Join Date: Feb 2016
Posts: 356
Originally Posted by Phanx View Post
I already don't know what the heck you've done there.
To be honest, I really dunno why I posted this LOL...

I surely needed some advice, but was totally aware of that this is just a garbage

I'm so embarrassed now

Last edited by Layback_ : 02-15-18 at 12:15 AM.
  Reply With Quote
02-15-18, 12:13 AM   #7
Layback_
An Onyxian Warder
Join Date: Feb 2016
Posts: 356
Originally Posted by Phanx View Post
I see you've already replied to the thread, so be aware I've edited the code in my last post several times in the meantime.
Yeap

Thanks for your solution!!

Last edited by Layback_ : 02-15-18 at 12:19 AM.
  Reply With Quote

WoWInterface » Developer Discussions » General Authoring Discussion » Toggling modules with proxy table

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off