separate modules within 1 addon
Hi there ladies / gents.
Over the last year or so, I've been self learning Lua and it's turned into a bit of a hobby where writing code has become more enjoyable than.. ehem.. playing the game! I've written a UI with optional integration into different aspects of the game that the user can disable/enable at will (ie Chat, Auction House etc etc). For clarity's sake, modules. Each module is a different Lua file within the one addon, so effectively, the TOC reads: Core.lua Auction_Module.lua Chat_Module.lua KeyBindButtonBox_Module.lua While the Core.lua file contains many functions that other modules use, functions within each module are created solely for that module. What I would very much like to do is this... If, say, the Chat module is shown as disabled in my DB on startup or reload, I'd like to be able to prevent any of that module's code from being read. I've experimented in several ways to do this. My most recent attempt was to call a function in Core.lua which would send a addon message with the 2nd arg being "load Chat Module". The chat_Module.lua in turn has an OnEvent script that would listen for that call and read/call the functions when it gets it. It works. But not very well. I've found that it never loads the chat script when I log in for the first time, but it always does when I reload. I'm guessing that the reason for this is that by the time the game has read (and called) my "load Chat Module" function in Core.lua, it hasn't even started reading Chat_Module.lua yet. Like I say, that's just my guess, I might be well off. Any suggestions for this would be greatly appreciated. I'm just very cautious about wasting memory if it's not required... especially with me being a beginner and all. P.S. Phanx, if you read this, thanks very much for your suggestions and code regarding setting up defaults for the addon's DB. Aanson. |
I would suggest putting the modules in their own LoD addon with the core as a dependency. Then whenever you need to load them, you can use LoadAddOn() on them. If you really want to continue having them contained in the single addon, then you could either make a toggle function in the module and either make that global so you can call it or put a pointer to it in the addon's private table so the core has access to it.
Here's an example of the second method using the addon's private table. Note, this is only accessible in Lua files, there is no equivalent for XML. In Chat_Module.lua Lua Code:
In Core.lua Lua Code:
This works because a vararg in the main chunk of your Lua files returns the Addon's string ID (the name of the folder your addon is contained in) and an empty local table generated on load that is shared among all of your Lua files. Note you can put the function call anywhere, but the variables need to be defined in the main chunk as the vararg changes if put in a function. |
Cheers Phantom,
Yeah that's how I have it just now. Well, the only difference is that in your example code, I've split 'addon' into two separate tables with the code: Lua Code:
But even with that, I still can't get it to work. The main reason I think is that I'd need to encompass all of my Chat_Module.lua functions within the ChatModuleEnable() function that you suggested in order to ensure that the code is only read if the module is enabled. Can I dare ask? On a scale of 1 to 10 on the bad practice scale, how bad would it be for the Chat_Module.lua functions to be read and stored to memory, but never called? (when the module is disabled, that is). Hope I'm making sense here. Aanson |
Quote:
Also, the vararg passed to addon Lua files gives the addon's name first, and the private table second, so your order is backwards: Code:
local addonName, addonPrivateTable = ... Code:
local F, V = unpack(addonPrivateTable) Quote:
Quote:
Core file loads first: Code:
addon.modules = {} Code:
function module:Enable() Code:
addon.db = { |
Whenever I need to have a set of functions specific to a module in the private table, I usually have a table specifically for the module and store it within the private table. This would produce something like the following.
Module1 Code:
local name,addon=...; Code:
local name,addon=...; Note you can use the private table like any other table and being shared among all Lua files of your addon opens it up to easily be used to create an internal API in whatever structure you want. |
Thank you
That sounds great. Phanx, apologies, I wrote that from memory yesterday and obviously didn't pay attention to what I was doing, I've copy / pasted now which might explain where I'm going with that first bit of code you quoted there:
Lua Code:
... but clearly from what you've said there, I'll be changing it to ... Lua Code:
Thank you for taking the time out to help guys. I think I'll def go with the format you provided and I like the idea of using separate tables within 'F' for each module. Thanks again! Aanson |
What I'm not understanding is why you're going with an array-style table (using addonTable[1] and addonTable[2])...
|
Yeah, that's likely because I didn't mention why. It's solely for the purpose of separating functions from variables/constants/defaults.
F stores only functions V.Defaults = {} V.Media = {} V.Colours = {} It's just my preference, nothing more. Aanson |
I think what he means is why are you calling it addonTable[1] instead of addonTable.Functions or whatever.
Also, "local F, V = unpack(select(2, ...))" is a very bizarre way of assigning those variables. You've already assigned "addonTable" to what you're pulling out with "select(2,...)" and using unpack could potentially be dangerous unless you're quite sure of the order of things. |
Could be that he doesn't know tables can have indicies of different types too.
Quote:
|
Well, he uses V.Defaults, etc. in his last post. The vararg might be throwing him off.
|
The addon-level vararg (...) always contains two values:
1. A string value containing the name of your addon's folder. 2. An empty table. You can modify the contents of the table, but you cannot change which string or which table the vararg contains. First, you're assigning those two values to the variables addonName and addonTable: Code:
local addonName, addonTable = ... Code:
addonTable[1] = {} Then you're using the unpack table to get references to the values in that table with the numeric keys 1 and 2 (unpack returns all values in a table with sequential 1-based numeric keys), instead of just looking them up directly by key. Then you're assigning those values back to the variables F and V. Hopefully with this spelled out, you can see how convoluted what you're doing is. If you want your addon's private table to contain two other tables, here is a more straightforward, more efficient, and less confusing way to do that: Code:
-- Assign local reference names to the contents of the vararg: Also note that unpack ignores key/value pairs where the key is not a sequential integer. If you have this table: Code:
local myTable = { |
Understood, thanks alot as always. It was very beneficial to have it broken down in that way.
I always knew it was a bit backwards. What I didn't realize though was that it is less efficient than other methods (ie just referencing addonTable direct). I was never worried about unpack() because the table keys were just 1 and 2, but I'll not be using it anymore. From what you've said, I don't want to be needlessly calling a function every time I reference the tables. Lua Code:
My intention with the final line is to have a global reference to addonTable. That way, when working on modules, I can easily reference to the table by using something like ... Lua Code:
... at the start of each module. Is it okay to do it in this way? |
Sorry, could I ask one other question about the examples you provided earlier regarding the processing of modules?
See if I were to define this function (copy/pasted from your examples below): Lua Code:
I'm sorry if this is a stupid question, but in this example where the function is called "ADDON_LOADED", I take it I am still required to create a handler frame and register to the event "ADDON_LOADED" and include a line like: Lua Code:
The reason I ask is because I've never actually defined a function using an event as it's name before. I've always just created a handler frame, given it an OnEvent handler and called each function that I want it to call when a particular event fires. I'm just wanting to rule out that simply defining the function is enough... ie because of the way in which it has been defined, would it automatically be called when the event fires rendering the above SetScript pointless? Thanks again. I hope I've been able to make the question clear enough. Aanson. |
To answer your question, that method will work and is about the same as the following. You can find more in depth detail at WoWWiki or WoWPedia on "handling events".
Lua Code:
|
Yes, you still need a frame to listen for events. Here's a simple snippet you can use to make events trigger methods of the same name on your addon table:
Code:
-- Create the frame: |
I don't think, that blindly hooking "OnEvent" is a good practice?
|
No one's hooking anything.
|
Setting an OnEvent script on your frame is totally normal, has nothing to do with hooking, does not effect events or their processing by anyone else's frames, and is in fact the only way to respond to events at all.
If you are used to registering events through AceEvent-3.0 or some other event handling library, well, that's all they do on the backend... they just add several layers of convoluted and completely unnecessary wrappers around it. Also you should familiarize yourself with the WoW API basics instead of blindly using libraries whose functionality you don't understand at all. :( |
Phanx, you making assumptions in the void :) Though, I do agree with your conclusions.
If something is simple as it is, you don't need to make it complicated. |
All times are GMT -6. The time now is 03:43 AM. |
vBulletin © 2024, Jelsoft Enterprises Ltd
© 2004 - 2022 MMOUI