04-25-14, 12:50 PM | #1 |
Module Namespace
This was brought to my attention by Phanx when she was helping me fix on of my modules for my addon:
Code:
-- You should fix your DB to use module namespaces properly: So this is my attempt at trying to fix this. This was the old db for modules (I think): Lua Code:
So I went thru and changed this to: Lua Code:
Now the following I seen in Postal to enable all the modules so I figured it was the correct way to do it (this is in my main Core:OnInitialize): Lua Code:
then this is the OnProfileChanged Lua Code:
Am I looking at this correctly or am I totally off base with my guess? Thanks Coke |
|
04-25-14, 05:41 PM | #2 |
Those look fine -- though you don't need to explicitly list all the modules; "*" is just fine -- but they have nothing to do with DB namespacing. I'd suggest copying from Mapster, as it's well-written, and its small size means it's easier to find the relevant parts of code.
Code:
local Addon = LibStub("AceAddon-3.0"):NewAddon("MyTestAddon") local db local defaults = { profile = { scale = 1.25, alpha = 1, showTheThing = true, showTheOtherThing = false, modules = { ["*"] = true, } } } function Addon:OnInitialize() self.db = LibStub("AceDB-3.0"):New("MyTestAddonDB", defaults, true) -- true is important! db = self.db.profile self.db.RegisterCallback(self, "OnProfileChanged", "Refresh") self.db.RegisterCallback(self, "OnProfileCopied", "Refresh") self.db.RegisterCallback(self, "OnProfileReset", "Refresh") local Dialog = LibStub("AceConfigDialog-3.0") local options = self:GetOptions() LibStub("AceConfigRegistry-3.0"):RegisterOptionsTable("MyTestAddon", options) Dialog:AddToBlizOptions("MyTestAddon", nil, nil, "general") for k, v in self:IterateModules() do if type(v.GetOptions) == "function" then options.args[k] = v:GetOptions() Dialog:AddToBlizOptions("MyTestAddon", nil, "MyTestAddon", k) end end options.args.profile = LibStub("AceDBOptions-3.0"):GetOptionsTable(self.db) options.args.profile.order = -1 Dialog:AddToBlizOptions("MyTestAddon", nil, "MyTestAddon", "profile") end function Addon:OnEnable() -- set up stuff here end function Addon:Refresh() db = self.db.profile -- update the upvalue to point to the new profile -- change stuff here for k, v in self:IterateModules() do local isEnabled, shouldEnable = v:IsEnabled(), self:GetModuleEnabled(k) if shouldEnable and not isEnabled then then self:EnableModule(k) elseif isEnabled and not shouldEnable then self:DisableModule(k) end if type(v.Refresh) == "function" then v:Refresh() end end end function Addon:GetModuleEnabled(moduleName) return db.modules[moduleName] end function Addon:SetModuleEnabled(moduleName, newState) local oldState = db.modules[moduleName] if oldState == newState then return end if newState then self:EnableModule(moduleName) else self:DisableModule(moduleName) end end local options function Addon:GetOptions() options = options or { type = "group", name = "MyTestAddon", args = { general = { order = 1, type = "group", name = "General Settings", args = { -- addon-wide settings here } } } } return options end Code:
local Addon = LibStub("AceAddon-3.0"):GetAddon("MyTestAddon") local Module = Addon:NewModule("MyTestModule") local db local defaults = { profile = { cats = true, size = 20, color = { r = 1, g = 1, b = 0, }, } } function Module:OnInitialize() self.db = Addon.db:RegisterNamespace("MyTestModule", defaults) db = self.db.profile self:SetEnabledState(Addon:GetModuleEnabled("MyTestModule") end function Module:OnEnable() -- set up stuff here end -- Leave this out if the module doesn't have any settings: function Module:Refresh() db = self.db.profile -- update the upvalue -- change stuff here end -- Leave this out if the module doesn't have any options: local options function Module:GetOptions() options = options or { type = "group", name = "MyTestModule", args = { -- module-specific settings here -- use tabs or inline for subgroups } } return options end
__________________
Retired author of too many addons. Message me if you're interested in taking over one of my addons. Don’t message me about addon bugs or programming questions. Last edited by Phanx : 04-25-14 at 05:52 PM. |
|
04-25-14, 06:57 PM | #3 | |
Does that mean I should have individual options for each module? I've seen on ElvUI that he has his options selt like: Lua Code:
so mine would be Lua Code:
Or am I looking to far into this? |
||
04-25-14, 10:06 PM | #4 |
Ok slowly but surely moving along with this.
Here is what I currently have done: BasicUI.lua the main part of the addon. Actionbars.lua for some reason the UnregisterEvent in this throws an error. Buffs.lua this one works. Unitframes.lua this one also is throwing and error except it is the RegisterEvent. Actionbar.lua error: Code:
5x BasicUI-5.4.7\Modules\Actionbars.lua:44: attempt to call method "UnregisterEvent" (a nil value) BasicUI-5.4.7\Modules\Actionbars.lua:44: in function <BasicUI\Modules\Actionbars.lua:37> (tail call): ? <in C code> <string>:"safecall Dispatcher[1]":9: in function <string>:"safecall Dispatcher[1]":5 (tail call): ? BasicUI-5.4.7\Libs\AceAddon-3.0\AceAddon-3.0-11.lua:543: in function "EnableAddon" BasicUI-5.4.7\Libs\AceAddon-3.0\AceAddon-3.0-11.lua:556: in function "EnableAddon" BasicUI-5.4.7\Libs\AceAddon-3.0\AceAddon-3.0-11.lua:636: in function <BasicUI\Libs\AceAddon-3.0\AceAddon-3.0.lua:621> <in C code> FrameXML\UIParent.lua:306: in function "UIParentLoadAddOn" FrameXML\UIParent.lua:329: in function "CombatLog_LoadUI" FrameXML\UIParent.lua:742: in function <FrameXML\UIParent.lua:705> Locals: Code:
17x BasicUI-5.4.7\Modules\Unitframes.lua:221: attempt to call method "RegisterEvent" (a nil value) BasicUI-5.4.7\Modules\Unitframes.lua:221: in function "ApplySettings" BasicUI-5.4.7\Modules\Unitframes.lua:119: in function <BasicUI\Modules\Unitframes.lua:91> (tail call): ? <in C code> <string>:"safecall Dispatcher[1]":9: in function <string>:"safecall Dispatcher[1]":5 (tail call): ? BasicUI-5.4.7\Libs\AceAddon-3.0\AceAddon-3.0-11.lua:543: in function "EnableAddon" BasicUI-5.4.7\Libs\AceAddon-3.0\AceAddon-3.0-11.lua:556: in function "EnableAddon" BasicUI-5.4.7\Libs\AceAddon-3.0\AceAddon-3.0-11.lua:636: in function <BasicUI\Libs\AceAddon-3.0\AceAddon-3.0.lua:621> <in C code> FrameXML\UIParent.lua:306: in function "UIParentLoadAddOn" FrameXML\UIParent.lua:329: in function "CombatLog_LoadUI" FrameXML\UIParent.lua:742: in function <FrameXML\UIParent.lua:705> Locals: nil Coke |
|
04-25-14, 10:59 PM | #5 |
Module is a table, not a WoW API Frame object. Lua tables have no notion of RegisterEvent or UnregisterEvent.
__________________
Whenever someone says "pls" because it's shorter than "please", I say "no" because it's shorter than "yes". Author of NPCScan and many other AddOns. |
|
04-26-14, 08:05 AM | #6 |
@Torhal:
AceAddon-3.0 module tables do have RegisterEvent and UnregisterEvent methods if you include AceEvent-3.0 as a mixin. @cokedrivers: You forgot to include AceEvent-3.0 when you declared your modules: Code:
local Module = Addon:NewModule("Actionbars", "AceEvent-3.0")
__________________
Retired author of too many addons. Message me if you're interested in taking over one of my addons. Don’t message me about addon bugs or programming questions. |
|
04-26-14, 08:11 AM | #7 | ||
Yes and no. Look at the example in my last post. Each module's options are defined in its own file, but they all end up in a single AceConfig options table, and are all accessed as sub-panels of a single options panel in the Interface Options window. Again, the primary benefit here is that your code is better organized and easier to maintain -- if you want to add a new setting to a module, you can add the default value, the option itself, and the code to apply it all in one file, instead of having to add code to the module file, add the default value to the addon core file, and add the option to yet another file.
Also, while I haven't spent any time looking at it in great detail, from what I have seen, I don't really think you should be leaning too heavily on ElvUI as an example of good coding practices. Any addon that begins every file with calls to unpack and select should probably be nuked from orbit.
__________________
Retired author of too many addons. Message me if you're interested in taking over one of my addons. Don’t message me about addon bugs or programming questions. Last edited by Phanx : 04-26-14 at 08:15 AM. |
|||
04-26-14, 08:49 AM | #8 | ||
Now all I have to do is figure out a sort for the new options layout. (You spoiled me with your help with the other options layout). Coke |
|||
04-27-14, 03:16 AM | #9 | |
Here's an example for the actionbar module: http://pastebin.com/8rGBw4Yi
__________________
Retired author of too many addons. Message me if you're interested in taking over one of my addons. Don’t message me about addon bugs or programming questions. |
||
04-27-14, 08:37 AM | #10 | |
Code:
function BasicUI:SetUpOptions() local options = GetOptions() -- @PHANX: add this to your options table instead of registering it separately: options.args.profile = LibStub("AceDBOptions-3.0"):GetOptionsTable(self.db) LibStub("AceConfig-3.0"):RegisterOptionsTable("BasicUI", options) -- @PHANX: You could write out each subkey but let's be lazy: local panels = {} for k in pairs(options.args) do -- this assumes all immediate children are groups if k ~= "welcome" and k ~= "profile" then -- skip these so we can add them manually as the first and last panels tinsert(panels, k) end end sort(panels) -- alphabetize so it looks nice and is easy to navigate local Dialog = LibStub("AceConfigDialog-3.0") -- Use the "welcome" panel as the main one: self.optionsFrame = Dialog:AddToBlizOptions("BasicUI", "BasicUI", nil, "welcome") -- Add all the rest as sub-panels: for i = 1, #panels do local k = panels[i] Dialog:AddToBlizOptions("BasicUI", options.args[k].name, "BasicUI", k) end -- Add the profile panel last: Dialog:AddToBlizOptions("BasicUI", options.args.profile.name, "BasicUI", "profile") end Code:
function Addon:OnInitialize() self.db = LibStub("AceDB-3.0"):New("BasicDB", defaults, true) -- true is important! db = self.db.profile self.db.RegisterCallback(self, "OnProfileChanged", "Refresh") self.db.RegisterCallback(self, "OnProfileCopied", "Refresh") self.db.RegisterCallback(self, "OnProfileReset", "Refresh") local Dialog = LibStub("AceConfigDialog-3.0") local options = self:GetOptions() LibStub("AceConfigRegistry-3.0"):RegisterOptionsTable("BasicUI", options) Dialog:AddToBlizOptions("BasicUI", nil, nil, "media") for k, v in self:IterateModules() do if type(v.GetOptions) == "function" then options.args[k] = v:GetOptions() Dialog:AddToBlizOptions("BasicUI", options.args[k].name, "BasicUI", k) end end options.args.profile = LibStub("AceDBOptions-3.0"):GetOptionsTable(self.db) options.args.profile.order = -1 Dialog:AddToBlizOptions("BasicUI", options.args.profile.name, "BasicUI", "profile") end EDIT: Added aPicture to show you what I mean. Last edited by cokedrivers : 04-27-14 at 06:37 PM. |
||
04-27-14, 04:54 PM | #11 | |
__________________
Whenever someone says "pls" because it's shorter than "please", I say "no" because it's shorter than "yes". Author of NPCScan and many other AddOns. |
||
04-27-14, 06:59 PM | #12 |
Ok I'm so excited after a long day of coding I finally have my whole BasicUI converted over to the way Phanx suggested. It's not perfect but it works and I think the code might be a little bit more understandable for those programmers out there.
So here are pastebins of the files: BasicUI.lua the main core of the addon. Actionbars.lua the Actionbars module. Buffs.lua the Buffs module. Castbars.lua the Castbar module. Chat.lue the Chat module. Datapanel.lua the Datapanel module. Minimap.lua the Minimap module. Miscellaneous.lua the Miscellaneous module. (with this I combined 11 files into 1 file) Nameplates.lua the Nameplates module. Powerbar.lua the Powerbar module. Tooltip.lua the Tooltip module. Unitframes.lua the Unitframes module. Darn pastebin I had to create an account to post all these LOL, no biggie. Well there they are in all there glory... well I feel proud but its all because of Phanx that I feel this way, they guided me along and I'm sure that not all the files are correct or all are the most efficient but they all work for now. Thanks Again everyone for your help. Coke |
|
04-28-14, 04:23 AM | #13 |
This should fix the sorting:
Code:
local panels = {} for k, v in self:IterateModules() do if type(v.GetOptions) == "function" then options.args[k] = v:GetOptions() tinsert(panels, k) end end sort(panels) for i = 1, #panels do local k = panels[i] Dialog:AddToBlizOptions("BasicUI", options.args[k].name, "BasicUI", k) end
__________________
Retired author of too many addons. Message me if you're interested in taking over one of my addons. Don’t message me about addon bugs or programming questions. |
|
04-28-14, 09:38 AM | #14 | |
I also was able to add back the SharedMedia support (see image below). Now beings I have been told to try to make everything more efficient would the following be an efficient way to have a global table for media in my UI? Code:
ADDON_NAME.media = {} function ADDON_NAME:UpdateMedia() -- Fonts self.media.fontNormal = LSM:Fetch("font", db.general.fontNormal) self.media.fontBold = LSM:Fetch("font", db.general.fontBold) self.media.fontItalic = LSM:Fetch("font", db.general.fontItalic) self.media.fontBoldItalic = LSM:Fetch("font", db.general.fontBoldItalic) self.media.fontNumber = LSM:Fetch("font", db.general.fontNumber) -- Background self.media.background = LSM:Fetch("background", db.general.background) -- Borders self.media.border = LSM:Fetch("border", db.general.border) self.media.panelborder = LSM:Fetch("border", db.general.panelborder) -- Statusbar self.media.statusbar = LSM:Fetch("statusbar", db.general.statusbar) -- Sound self.media.sound = LSM:Fetch("sound", db.general.sound) end Then in the ADDON_NAME:OnInitialize() function I call self:UpdateMedia(). Is this the correct way to do it or is there a better way. Also is there a way to adjust the timer size and format for buffs? the default has the space and when I have 2 buffs with timers next to each other they overlap. Thanks Again Coke |
||
04-28-14, 02:28 PM | #15 |
The media thing looks fine, except that ADDON_NAME is (I assume) a string value, instead of your addon table, so you should probably change that... or change the variable name if it actually points to an object instead of a name string.
Code:
local ADDON_NAME, private_table = ... -- ADDON_NAME is a string containing the name of your addon's folder and TOC file, eg. "BasicUI" -- private_table is a table that exists only for the files in your addon -- You can name these FLYING_BANANAS and cat_potato if you want, it doesn't matter. Also, don't put that local L = setmetatable... block in every file. Put it in whichever file loads first, and add it to the addon object, eg. Code:
local BasicUI = LibStub("AceAddon-3.0"):NewAddon("BasicUI") BasicUI.L = L Code:
local BasicUI = LibStub("AceAddon-3.0"):GetAddon("BasicUI") local L = BasicUI.L -------------------------------------------------- Registering fonts with LSM as "BasicUI Normal" and "BasicUI Bold" is probably not the best practice... use the actual font name. You should probably set width = "double" on those media dropdowns, especially the backdrop and border ones, so you can actually see the names. -------------------------------------------------- As for the buff text, there's surely a way to adjust it... which file is doing that? All I see in the Buffs module file is a scale change.
__________________
Retired author of too many addons. Message me if you're interested in taking over one of my addons. Don’t message me about addon bugs or programming questions. |
|
04-28-14, 02:33 PM | #16 |
I think its blizzard default. As you said I haven't changed anything except the font size and style. I would just like to get rid of the space ( Default = 60 m vs What i want = 60m ).
|
|
04-28-14, 04:06 PM | #17 |
Code:
DAY_ONELETTER_ABBR = gsub(DAY_ONELETTER_ABBR, "%s", "") HOUR_ONELETTER_ABBR = gsub(HOUR_ONELETTER_ABBR, "%s", "") MINUTE_ONELETTER_ABBR = gsub(MINUTE_ONELETTER_ABBR, "%s", "") SECOND_ONELETTER_ABBR = gsub(SECOND_ONELETTER_ABBR, "%s", "")
__________________
Retired author of too many addons. Message me if you're interested in taking over one of my addons. Don’t message me about addon bugs or programming questions. |
|
04-29-14, 09:00 AM | #18 | |
Kinda off topic but not should I move my post in the other section to here beings we are talking about libs and code? Coke |
||
12-06-16, 11:06 PM | #19 |
Really late to the party, and sorry for thread necro, but Google and all that...
If you know you are going to need one or more embeddable libraries in each module, you can do the following. Just remember it only works on libraries that have a mixin, or are embed-capable, so it won't work on LibDataBroker-1.1 or LibWindow-1.1, as examples. Lua Code:
Okay, question time. If I wanted a load on demand options AddOn that plugged into AceConfig-3.0 for the "core" AddOn, how would that be done? Also, I see the magic ["*"] thing, which I more or less understand. Why not use ["**"] instead? Then, in the AceConfig-Options docs, besides the ubiquitous "args", there is also a "plugins" type. Should that not be used instead of "modules"? |
|
WoWInterface » Developer Discussions » Lua/XML Help » Module Namespace |
«
Previous Thread
|
Next Thread
»
|
Display Modes |
Linear Mode |
Switch to Hybrid Mode |
Switch to Threaded Mode |
|
|