Thread Tools Display Modes
11-14-12, 03:36 PM   #1
Elderin
A Deviate Faerie Dragon
Join Date: Nov 2012
Posts: 17
Accessing Global Data

Let me begin by stating that I have a MyAddon.xml file and a MyAddon.lua file that are properly aware of and function correctly with each other. Additionally, the xml file defines the UI and the lua file contains needed functions, variables, etc.

My assumption: The names of Frame and FontString entities which are defined in my xml file are available as global variables.

The answer to my question is more likely about convention. It seems that within the lua file, after things are loaded, etc., I can access the Frame objects or Fontstring objects directly by name and perform associated functions such as shown below:
Code:
in xml
<FontString inherits="GameFontNormal" name="MyFontStr_1" text="Title x">
...
</FontString>

in lua file
MyFontStr_1:SetText("Title One");
_G.MyFontStr_1:SetText("Title One");
_G["MyFontStr_1"]:SetText("Title One");
getglobal("MyFontStr_1"):SetText("Title One");
I am aware that the _G methods seem to be replacements for getglobal(). And, I also see that using any of the last three allows me to dynamically create the name of the object
Code:
local x = 1;
_G["MyFontStr_"..x]:SetText("Title "..x);
It appears that the four methods shown all change the text value of the FontString object. The question is: Functionaly, are there any differences? Any reason to use one over the other? Or, is it just whatever I myself am comfortable with?

While I have used a FontString as the example of my question, I also assume that these different approachs could be applied to any of the global data that is present at run time.
  Reply With Quote
11-14-12, 04:12 PM   #2
Dridzt
A Pyroguard Emberseer
 
Dridzt's Avatar
AddOn Author - Click to view addons
Join Date: Nov 2005
Posts: 1,359
Unless you are trying to modify/revive an existing addon in which case you may want to avoid an extensive re-write,
it's best if you use the frame manipulation API both to create and script your frames from lua, without using xml.

As to your actual question.
#4 is deprecated and should not be used (it means Blizzard can disable it at their convenience since they've warned it's to be phased out)
#3 and #2 are equivalent, the difference is only in style as long as the key to the table is a contiguous string.
If you had spaces in the name then table["two words"] needs to be used t.two words will not work.
#1 makes an implicit lookup in the global table but is otherwise the same as #2 and #3.
  Reply With Quote
11-14-12, 04:13 PM   #3
Torhal
A Pyroguard Emberseer
 
Torhal's Avatar
AddOn Author - Click to view addons
Join Date: Aug 2008
Posts: 1,196
You shouldn't use getglobal(), as it's not only deprecated but is now actually a function-wrapper around _G and is thus actually slower due to the overhead of the function call.

The rest are functionally equivalent, the main difference being syntactic sugar. The only time I use _G["whatever"] is when I am passing in an unknown string (as through a function parameter) or constructing a string; otherwise I use _G.whatever.

Edit: Damn it, Dridzt!
__________________
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.
  Reply With Quote
11-14-12, 04:16 PM   #4
semlar
A Pyroguard Emberseer
 
semlar's Avatar
AddOn Author - Click to view addons
Join Date: Sep 2007
Posts: 1,060
The getglobal function is deprecated and shouldn't be used for anything. In terms of performance you're essentially looking up "getglobal" in _G in the first place, then the overhead of a function call plus another lookup in _G for whatever you're trying to access.

I personally just use the variable name when I need to access it with two exceptions. If I have a variable with the same name in a more local scope and need to get to the global I would use _G["var"], and if I need to dynamically create the variable name I could concatenate the key together.

_G.var is just syntactic sugar for _G["var"].
  Reply With Quote
11-14-12, 05:30 PM   #5
SDPhantom
A Pyroguard Emberseer
 
SDPhantom's Avatar
AddOn Author - Click to view addons
Join Date: Jul 2006
Posts: 2,313
Originally Posted by Elderin View Post
Code:
MyFontStr_1:SetText("Title One");
_G.MyFontStr_1:SetText("Title One");
_G["MyFontStr_1"]:SetText("Title One");
getglobal("MyFontStr_1"):SetText("Title One");
Originally Posted by Dridzt View Post
#1 makes an implicit lookup in the global table but is otherwise the same as #2 and #3.
As stated, #2 and #3 are exactly the same in both function and performance, however #1 is faster since it only requires a single index operation. #2 and #3 have to index _G from the global environment, which is a reiteration of itself, then index MyFontStr_1 from the resulting table. This requires 2 indexing operations and is therefore much slower in comparison. Note the number of indexing operations are measured before the processing of FontString:SetText(), which adds a couple more indexing operations to it (one to check the FontString table and the other to default into its metatable).

To break down the use of each, #1 is best if you need to access just one object directly. #3 would be for dynamically accessing from a list of objects in which you need to apply values to a name in order to construct it. #2 has no practical use. It has nothing more to offer than #1 and uses up more CPU to process for the same result.
__________________
WoWInterface AddOns
"All I want is a pretty girl, a decent meal, and the right to shoot lightning at fools."
-Anders (Dragon Age: Origins - Awakening)

Last edited by SDPhantom : 11-14-12 at 05:40 PM.
  Reply With Quote
11-14-12, 05:40 PM   #6
Elderin
A Deviate Faerie Dragon
Join Date: Nov 2012
Posts: 17
Thanks, all.

Originally Posted by Dridzt View Post
Unless you are trying to modify/revive an existing addon in which case you may want to avoid an extensive re-write, it's best if you use the frame manipulation API both to create and script your frames from lua, without using xml.
It seems like I read somewhere that Blizz preferred UI definitions in the separate xml file. However, most books on addons are relatively few and older now. I recently read on a forum that it was considered better and more elegant to do it all in lua now. When it comes to coding, I am all about elegant. However, I am currently working on a project based on a quite old addon long since not supported. And so, trying not to do a complete rewrite even though much does not resemble the original stuff and so far, I have added a lot. Perhaps my next iteration will be doing away with the xml file.

Thanks, again, guys.

Last edited by Elderin : 11-14-12 at 05:43 PM.
  Reply With Quote
11-14-12, 05:52 PM   #7
Seerah
Fishing Trainer
 
Seerah's Avatar
WoWInterface Super Mod
Featured
Join Date: Oct 2006
Posts: 10,860
Right - Blizz prefers to do it that way. But they don't care how you do it.

The only time you really need XML is if you are defining a template to use and a frame-factory type function won't suffice.
__________________
"You'd be surprised how many people violate this simple principle every day of their lives and try to fit square pegs into round holes, ignoring the clear reality that Things Are As They Are." -Benjamin Hoff, The Tao of Pooh

  Reply With Quote
11-14-12, 09:53 PM   #8
SDPhantom
A Pyroguard Emberseer
 
SDPhantom's Avatar
AddOn Author - Click to view addons
Join Date: Jul 2006
Posts: 2,313
Most people prefer to use Lua over XML. I really don't see any proof either way on long term performance impacts. The idea was that XML was for static UI structures while you'd use Lua for creating dynamic frames. With nearly everything being supported in Lua, pretty much everyone has phased out XML. I think the tree-like XML structure is easier to read and understand in this fashion than lines of linear Lua code. That's just my preference though. It's up to you to decide which way you want to go.
__________________
WoWInterface AddOns
"All I want is a pretty girl, a decent meal, and the right to shoot lightning at fools."
-Anders (Dragon Age: Origins - Awakening)
  Reply With Quote
11-15-12, 02:09 AM   #9
Vlad
A Molten Giant
 
Vlad's Avatar
AddOn Author - Click to view addons
Join Date: Dec 2005
Posts: 793
Shame we can't write templates using lua.
__________________
Profile: Curse | Wowhead
  Reply With Quote
11-15-12, 02:15 AM   #10
Phanx
Cat.
 
Phanx's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2006
Posts: 5,617
The biggest problem with XML is that it's incredibly verbose, and is just a hassle to write by hand.

Also, using XML, all references must be global, which is another big argument against it. While in Lua you can write:

Code:
local f = CreateFrame("Frame")
f:RegisterEvent("ADDON_LOADED")
f:SetScript("OnEvent", MyAddOn.EventHandler)
... if you're using XML, you have to create 1-3 globals and 1-2 functions to achieve the same thing.

Firstly, you have to give the frame a global name, or you won't be able to access it from your Lua code.

Secondly, you have to create an anonymous function to register the event in an OnLoad script, or a global function to be assigned as the OnLoad script.

Finally, you either have to make MyAddOn.EventHandler a global function outside of the MyAddOn table (eg. instead of function MyAddOn:EventHandler() ... end you'd need function MyAddOn_EventHandler(MyAddOn) ... end) or double up on function calls by creating another anonymous wrapper function:

Code:
<Frame name="SomeGlobalSpam">
	<Scripts>
		<OnLoad>
			self:RegisterEvent("ADDON_LOADED")
		</OnLoad>
		<OnEvent>
			MyAddOn:EventHandler(event, ...)
		</OnEvent>
	</Scripts>
</Frame>
__________________
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.
  Reply With Quote
11-15-12, 05:26 AM   #11
SDPhantom
A Pyroguard Emberseer
 
SDPhantom's Avatar
AddOn Author - Click to view addons
Join Date: Jul 2006
Posts: 2,313
If you really want XML code to be inaccessible to the global environment, you can clean up after registering a script handler. Furthermore, the following XML structure can be rewritten to use one less stack position in its script handlers.

Code:
<Frame>
	<Scripts>
		<OnUpdate>
			MyAddonFrame_OnUpdate(self,elapsed);
		</OnUpdate>
	</Scripts>
</Frame>
Rewritten to:

Code:
<Frame>
	<Scripts>
		<OnUpdate function="MyAddonFrame_OnUpdate"/>
	</Scripts>
</Frame>
This takes the pointer set to the global MyAddonFrame_OnUpdate and directly sets it as the OnUpdate handler instead of creating a function wrapper. After that, you may erase the global variable and the frame will still run the function.
__________________
WoWInterface AddOns
"All I want is a pretty girl, a decent meal, and the right to shoot lightning at fools."
-Anders (Dragon Age: Origins - Awakening)

Last edited by SDPhantom : 11-16-12 at 10:35 AM.
  Reply With Quote
11-15-12, 11:41 PM   #12
Elderin
A Deviate Faerie Dragon
Join Date: Nov 2012
Posts: 17
First, Phantom, I assume all references to OnLoad should be replaced with OnUpdate. Otherwise, I am a bit lost.

However. in the first part of your example it is fairly obvious that the OnUpdate function is being passed two arguments - self and elapsed - explicitly.

In the rewritten version, where only the function name is declared, do we know what parameters the function will actually receive?

Last edited by Elderin : 11-15-12 at 11:43 PM.
  Reply With Quote
11-15-12, 11:59 PM   #13
semlar
A Pyroguard Emberseer
 
semlar's Avatar
AddOn Author - Click to view addons
Join Date: Sep 2007
Posts: 1,060
It receives all the arguments attached to the event.

In your lua file you would just have something like
lua Code:
  1. function MyAddonFrame_OnUpdate(self, elapsed) etc. end
  Reply With Quote
11-16-12, 12:30 AM   #14
SDPhantom
A Pyroguard Emberseer
 
SDPhantom's Avatar
AddOn Author - Click to view addons
Join Date: Jul 2006
Posts: 2,313
Originally Posted by Elderin View Post
First, Phantom, I assume all references to OnLoad should be replaced with OnUpdate. Otherwise, I am a bit lost.
I chose to use the OnUpdate handler in the example at random. The function property is available to all script handler tags. The post was to demonstrate a flexibility in the XML schema and not actual code to use.



Originally Posted by Elderin View Post
However. in the first part of your example it is fairly obvious that the OnUpdate function is being passed two arguments - self and elapsed - explicitly.

In the rewritten version, where only the function name is declared, do we know what parameters the function will actually receive?
The second method receives all values through the function's argument list, just like any other function in Lua. See Widget handlers for a complete list of all script handlers for every widget and the order of their arguments passed. Note using this method, you can assign different names to the arguments if you wish. It doesn't change the functionality any.
__________________
WoWInterface AddOns
"All I want is a pretty girl, a decent meal, and the right to shoot lightning at fools."
-Anders (Dragon Age: Origins - Awakening)
  Reply With Quote
11-16-12, 02:53 AM   #15
Phanx
Cat.
 
Phanx's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2006
Posts: 5,617
Originally Posted by Elderin View Post
I assume all references to OnLoad should be replaced with OnUpdate.
No. Those are separate scripts, with totally different purposes. The OnLoad script is only called once, after all of the frame's XML is read. The OnUpdate script is called every time a new video frame is drawn, so potentially 100+ times every second.

It's also worth mentioning that OnLoad scripts are unnecessary in Lua, and in fact aren't even supported in Lua; you just declare the frame and then do stuff with it immediately.
__________________
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.
  Reply With Quote
11-16-12, 06:36 AM   #16
Elderin
A Deviate Faerie Dragon
Join Date: Nov 2012
Posts: 17
Sorry, guys, I was just looking at the specific code in the example. I was just referring to the mix of tags and functions. I just confused things with my statement about changing the Onload (magenta colored) to OnUpdate (green colored). My bad. I apologize.

Originally Posted by SDPhantom View Post
If you really want XML code to be inaccessible to the global environment, you can clean up after it in an OnLoad handler. Furthermore, the following XML structure can be rewritten to use one less stack position in its script handlers.

Code:
<Frame>
	<Scripts>
		<OnUpdate>
			MyAddonFrame_OnUpdate(self,elapsed);
		</OnLoad>
	</Scripts>
</Frame>
Rewritten to:

Code:
<Frame>
	<Scripts>
		<OnUpdate function="MyAddonFrame_OnUpdate"/>
	</Scripts>
</Frame>
This takes the pointer set to the global MyAddonFrame_OnLoad and directly sets it as the OnLoad handler instead of creating a function wrapper. After that, you may erase the global variable and the frame will still run the function.
Thanks for the link to the Widget Handlers. Sigh. So much to learn, so little time.

Last edited by Elderin : 11-16-12 at 06:39 AM.
  Reply With Quote
11-16-12, 10:15 AM   #17
SDPhantom
A Pyroguard Emberseer
 
SDPhantom's Avatar
AddOn Author - Click to view addons
Join Date: Jul 2006
Posts: 2,313
The thinking behind the change to demonstrate with the OnUpdate handler instead was that it runs continually whereas OnLoad runs only once. This was to display the ability to delete the global and show that the handler would still run afterward. I corrected my other post to make the full switch, I thought I had caught all of the OnLoad references, but apparently, there were more. I didn't even notice until now, yesterday was an off day for me.
__________________
WoWInterface AddOns
"All I want is a pretty girl, a decent meal, and the right to shoot lightning at fools."
-Anders (Dragon Age: Origins - Awakening)

Last edited by SDPhantom : 11-16-12 at 10:38 AM.
  Reply With Quote
11-16-12, 10:21 AM   #18
SDPhantom
A Pyroguard Emberseer
 
SDPhantom's Avatar
AddOn Author - Click to view addons
Join Date: Jul 2006
Posts: 2,313
Originally Posted by Phanx View Post
It's also worth mentioning that OnLoad scripts are unnecessary in Lua, and in fact aren't even supported in Lua; you just declare the frame and then do stuff with it immediately.
The reason for this is because the OnLoad handler fires before CreateFrame() returns. If you create a template with an OnLoad handler, then inherit it with a CreateFrame() call, it would run.
__________________
WoWInterface AddOns
"All I want is a pretty girl, a decent meal, and the right to shoot lightning at fools."
-Anders (Dragon Age: Origins - Awakening)
  Reply With Quote

WoWInterface » Developer Discussions » Lua/XML Help » Accessing Global Data

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