WoWInterface

WoWInterface (https://www.wowinterface.com/forums/index.php)
-   General Authoring Discussion (https://www.wowinterface.com/forums/forumdisplay.php?f=20)
-   -   Addon file system structuring (https://www.wowinterface.com/forums/showthread.php?t=30311)

Amenity 01-28-10 12:51 PM

Addon file system structuring
 
I'm sure this has probably come up at some point but I couldn't find anything on it in my searches...so sorry if this is oft-repeated.

Hypothetical scenario: I've got a clock addon. Due to my anal-retentiveness, it's separated into the following files:

clock.lua --All the frames & appearance-related stuff defined here.

thingus.lua --The actual timing function.

clock.toc --Self-explanatory.


1. Is there any reason not to do this?

2. When loading multiple Lua files in a single addon, are they simply appended to the preceeding file in-order as defined in the ToC? Or are they handled as "separate addons"? Example with two files:

Code:

local thingus = somevalue
Code:

function dostuff(when)
    print(thingus)
end

Will that toss an error? Or is the second file appended to the end of the first, making thingus a defined value for the dostuff function?

3. Assuming an addon of considerable size, is it better to have many small files or a few/one large file?

4. Assuming file structure "matters", how does directory structure factor into this?

Thanks in advance! :)

Xrystal 01-28-10 12:57 PM

They are loaded in the sequence listed in the TOC but local entities in one file can only be accessed via another file if there is a non lock function to grab them.

I have used that functionality with my LootAlerter addon with all the data in one file, common functions in another etc. The downside is that functions that you want to use outside of the file will mean they are in the public domain and naming conflicts could get in the way. The upside is that the code is separated for easier access to source data.

If the addon will be less than 500 or even more lines stick with just the one file to avoid the non local issue at least. If you do need them split up, try and find a way to maximize the use of the local option so that only what you need to be public is public and that it is unique to your addon enough for it not to get mixed up.

I've course that is just my view and understanding on things. I have always learning that local is good. The more localised the better.

Rilgamon 01-28-10 01:02 PM

New file, new variables. Nothing is shared.
Last patch added an argument call to every file.
So there is a table you can use for all files and that
keeps values set in one file. I have an init.lua that I use
for nearly all new addons with something like this

Code:

local name, table = ...

if(name) then
  table.version = GetAddOnMetadata(name,"Version") or '0.0'
  table.author = GetAddOnMetadata(name,"Author") or '<Nobody>'
  table.appinfo = GetAddOnMetadata(name,"Notes-"..GetLocale()) or GetAddOnMetadata(name,"Notes") or '<No Info>'
  table.title = GetAddOnMetadata(name,"Title-"..GetLocale()) or GetAddOnMetadata(name,"Title") or name
  table.character = UnitName("player")
  table.crealm = GetRealmName()
  table.faction,_ = UnitFactionGroup('player')
end


Xrystal 01-28-10 01:06 PM

Oh, not heard about that. So ... are the values contained in that table at that time ?

So I could keep my data separate and localized and it will be accessible in other files loaded after ? Or am I missing something ?

Amenity 01-28-10 02:25 PM

Quote:

Originally Posted by Xrystal (Post 176489)
Oh, not heard about that. So ... are the values contained in that table at that time ?

So I could keep my data separate and localized and it will be accessible in other files loaded after ? Or am I missing something ?

I'm a bit confused myself. How exactly is that method any different from any other local variable generation in a previously-loaded file? Looks like you're just making a table. What am I missing? :confused:

p3lim 01-28-10 02:31 PM

The table is kinda a local global, for usage within any files of the addon in question.

No matter what file you add stuff to that table it will stick to all files.

Its very good to use for stuff like embedding and localization.

Shadowed 01-28-10 02:41 PM

It's a way of making your addon more self contained, before if you spread an addon out between multiple files you had to have a global somewhere.

Before you would have to do something like:

Code:

-- localization.enUS.lua
AddonLocals = {["foo"] = "foo"}

-- Addon.lua
local Addon = {}
local L = AddonLocals

Now you can do:

Code:

-- localization.enUS.lua
local Addon = select(2, ...)
Addon.L = {["foo"] = "foo"}

-- Addon.lua
local Addon = select(2, ...)
local L = Addon.L

It really just gives you cleaner syntax.

Amenity 01-28-10 02:47 PM

Quote:

Originally Posted by p3lim (Post 176502)
The table is kinda a local global, for usage within any files of the addon in question.

No matter what file you add stuff to that table it will stick to all files.

Its very good to use for stuff like embedding and localization.

Right, I understood that part. My sense of confusion is how it does this.

I think my confusion has to do with my ignorance of calling name as an argument to if. In other words, he's doing this:

Code:

local name, table = ...

if(name) then
    blahblahtablecrap
end

And I'm thinking this:

Code:

local name, table = ...

if name then
    blahblahtablecrap
end

I'm also assuming that ellipsis use in Lua is similar to C (i.e., "variable number of whatever").

Xrystal 01-28-10 02:53 PM

Very interesting. So where is the original information on this as I can't see it in the UI forums 3.3 changes.

What other values are in ... From the looks of it the first argument is the addon's name and the second one is its global table. Any other information in there ?

So say in my localization.enUS.lua file I currently do this.
<MyAddon>Translator_L["DescriptiveName"] = "Translated Text"

And then in my main addon I would usually do something like this.
local _L = <MyAddon>Translator_L;
print(_L["DescriptiveName"])


Instead I can now do this ?
AddonData = select(2,...)
AddonData.Translator_L["DescriptiveName"] = "Translated Text"

AddonData = select(2,...)
local _L = AddonData.Translator_L;

As long as each file in that addon you want to update and/or use the addons data will need to add that first line each time? So in essence they have created a global table for all addons that are loaded on the system ? Whether or not the values are used ?

Torhal 01-28-10 02:55 PM

The parentheses are unnecessary in the same manner as a semicolon is unnecessary - in most cases. Only when attempting to disambiguate (in the case of an if) or use all on one line (in the case of semicolon when using /script within WoW) are they necessary.

Shadowed 01-28-10 03:10 PM

Quote:

Originally Posted by Xrystal (Post 176508)
Very interesting. So where is the original information on this as I can't see it in the UI forums 3.3 changes.

What other values are in ... From the looks of it the first argument is the addon's name and the second one is its global table. Any other information in there ?

So say in my localization.enUS.lua file I currently do this.
<MyAddon>Translator_L["DescriptiveName"] = "Translated Text"

And then in my main addon I would usually do something like this.
local _L = <MyAddon>Translator_L;
print(_L["DescriptiveName"])


Instead I can now do this ?
AddonData = select(2,...)
AddonData.Translator_L["DescriptiveName"] = "Translated Text"

AddonData = select(2,...)
local _L = AddonData.Translator_L;

As long as each file in that addon you want to update and/or use the addons data will need to add that first line each time? So in essence they have created a global table for all addons that are loaded on the system ? Whether or not the values are used ?

It was in 3.3 so it should be there. First argument is the addons folder name, second is the table. Saying it's global isn't accurate thought, it's really just a local table that's shared between the files loaded in the addon folder. No other addon can access it short of adding their own file that is loaded from your TOC.

But yes, you could change it to that.

p3lim 01-28-10 03:13 PM

Quote:

Originally Posted by Xrystal (Post 176508)
AddonData = select(2,...)
AddonData.Translator_L["DescriptiveName"] = "Translated Text"

Mind the local, else its just global again.

SDPhantom 01-28-10 03:15 PM

To better explain how WoW passes the new global vararg expression, I'm going to put up examples of before and after in context of function wrapping.

ToC File:
Code:

File1.lua
File2.lua

WoW 3.2:
Code:

local function File1()
-- File1.lua run as code chunk
end;
File1()

local function File2()
-- File2.lua run as code chunk
end;
File2()

WoW 3.3:
Code:

local function LoadAddOn(AddOnName)
        -- Note AddOnName contains the folder name of the addon
        local AddOnTable={};

        local function File1(...)
        -- File1.lua run as code chunk
        end;
        File1(AddOnName,AddOnTable)

        local function File2(...)
        -- File2.lua run as code chunk
        end;
        File2(AddOnName,AddOnTable)

        -- And so on...
end;


Xrystal 01-28-10 03:47 PM

rofl, might have to play with it a bit to get full understanding of it :D

basically we can now have every variable local and that addon table will allow us access ? Or am I still confused ? rofl

SDPhantom 01-28-10 04:01 PM

Quote:

Originally Posted by Xrystal (Post 176518)
rofl, might have to play with it a bit to get full understanding of it :D

basically we can now have every variable local and that addon table will allow us access ? Or am I still confused ? rofl

Ya, just think of it as an upvalue passed to the entire addon, although it isn't available to the XML files, just the Lua ones.

Torhal 01-28-10 04:02 PM

Do this in every file:

Code:

local addon_name, addon_table = ...
Then, in File1, you can do this:

Code:

function addon_table:PrintHello()
        print(string.format("Hello! This AddOn is named %s", addon_name))
end

In File2, you can then call:

Code:

addon_table:PrintHello()
...and get what you'd expect.

Xrystal 01-28-10 04:10 PM

Aha, yep, thats what I envisioned, but kept forgetting functions are objects too :D

Might make some of my addons more cleaner working that way :D

Xrystal 01-28-10 04:40 PM

Oh, I don't believe I missed it rofl .. The amount of times I've read this post http://forums.worldofwarcraft.com/th...37376853&sid=1 and I never saw the part about the addon stuff.

Quote:

ADDON LOADING
When a .lua file is loaded you can now access the name of the AddOn containing it, and an AddOn specific table (essentially an AddOn variable scope) by assigning them from ...:

local addonName, addonTable = ...;

The same table is sent to every file in a particular AddOn (each AddOn gets its own table).
Something to think on when I next do some updates to my addons where this would be beneficial.

Rilgamon 01-28-10 04:57 PM

To reduce the confusion this part
Code:

if(name) then

end

is not required. The first argument is always set.
Dont know why I still have it ;)

Xrystal 01-28-10 04:59 PM

Rofl, thanks for the clarification there :D Was trying to think of times when it wouldn't exist :D


All times are GMT -6. The time now is 09:39 AM.

vBulletin © 2024, Jelsoft Enterprises Ltd
© 2004 - 2022 MMOUI