Guide to XML frames part1

Reviewing RoM's Add-on Loading Process
RoM loads add-ons by first scanning through the  folder and looking for any sub-folders in lexicographic order. When it finds a sub-folder, the game then looks inside for a file with the same name as the folder and a .TOC extension. This TOC file (Table Of Contents) is merely a text file that lists all the files the game client should load, in the order listed, to activate this add-on. This loading procedure has a few effects that add-on developers need to be aware of.
 * Add-ons with names lower in lexicographical order than others will get loaded first.
 * An add-on can be disabled by merely renaming its folder or its TOC file.
 * The order an add-on's files are listed within the TOC can be important.

A dime tour of XML
XML (eXtensible Markup Language) is a text-based markup language created by the World Wide Web Consortium (W3C) to provide a standardized way for storing structured information such as data, documents, invoices, etc. Those already familiar with HTML will find several similarities with XML, though there are differences. We won't be exploring them in this tutorial. There are however, several XML tutorials available online as well as W3C's descriptions.

At it's heart XML is a hierarchical, tag based description language (in XML parlance, these are actually called elements, but I'll stick to the word tag throughout this tutorial). That is, it uses tags, to define the data to be associated with the tag, and we can define a hierarchy of these tags. Further, tags can also have attributes. We'll explore this more as this tutorial progresses, but for now we should simply familiarize ourselves with how XML itself works.

We define tags with a name enclosed in angled brackets ('<' and '>'), and close the tag with the same name in angled brackets, but with a slash at the start of the name. Everything in between these is the contents of the tag. As mentioned, tags can also have attributes. These are defined immediately after the name of the tag, but before the closing angled bracket of the tag itself. There is also a short form of the closing tag that uses the slash right before the closing angled bracket. As a simple example, imagine a store that sells DVD videos. We might define a list of DVD box sets this store sells in the following way (ignore the actual values given, they are just pulled from thin air):

In the above,,  ,  ,   and   are the tags, and  ,  ,  , and   are the closing tags. Notice how the  tag uses the short form for closing its tag. Further,  is an attribute of the   tag, and   is an attribute of the   tag. The hierarchy is therefore defining a product listing that has a title and multiple products. Each of these products has a name, a price, and a sorting category. There is of course a lot more to XML than what is shown here, but this should be enough to get us started.

Framing RoM
Runes of Magic, at least from the view of its interface, is centered around the concept of the frame. It is so basic that very few add-ons are without at least one frame. Even those add-ons that don't define a frame for themselves will often hook themselves onto some other pre-existing frame. It is through frames that the game interacts with an add-on, and also serves as the interaction point with users. So the natural question then is what exactly is a frame? A frame is an abstract data type that allows us to define a rectangular region on the screen. This region can further be interacted with by the user, be an anchor point for other objects, as well as receive and react to messages from the game client. This last is one of the more important aspects to understand about frames. It is the game client, via frames, that typically calls the functions in an add-on; not the other way around. There are effectively two ways the game client does this via frames. The first is through some pre-defined Lua code snippets, the second through events. We'll also see that this last is really nothing more than an extension of the code snippet method.

Frames are also hierarchical and rarely, if ever, stand alone. Typically, frames are attached to others as sub-frames. This is called parenting. Frames that have other frames attached to them are called the parent of those sub-frames, and those sub-frames are called child frames or children of the frame. A way to think about this parent-child relationship is as a family tree, which is where the terms come from. For frames, though they can have many children, they only ever have one parent.

The parent-child relationship goes further than just in name as well. Any child frames will inherit some of the attributes of its parent frame. Namely scale, opacity, position and visibility. If a frame is hidden or shown, all child frames also get hidden or shown.

Starting the example add-on
We'll be creating an add-on that displays the amount of memory used by Lua and will periodically update this information. So we start the add-on by creating the add-on's sub-folder in the  folder. I'll call this add-on MemViewer, so make a  folder and inside create the three text files: ,  , and.

Open  and add the following (lines starting with   are optional):

Remember, this is merely the list of files that the game client will load, in the order listed. We'll want the code in the Lua file loaded first since we'll be referencing some of the functions we create as part of the frame definition in the XML file. Save the file and open.

Ensuring valid XML
When the Runes of Magic game client loads an XML file, the first thing it does is attempt to validate it. If this validation fails, the game client will simply refuse to load the file. Obviously, we would like to have a valid XML file as well. We can ensure this by telling the game which definition we are using, and we do this by providing a special tag at the start of our XML file. You don't need to worry too much about the meaning of the attributes. Just know that it is needed, and it is the same for all the XML files we'll be creating for add-ons (I will however mention about the last attribute later).

Add the following to the XML:

As this first line is the same regardless, you can either copy the line above or open one of RoM's XML files or even get it from another add-on. As it is the very first tag for our XML we also need the closing tag at the end of the file. Put a few blanks lines in between for adding things in later. Save the file, but don't close it yet. I suggest making a copy of this blank XML for starting other projects. This way you won't have to go hunt around for this same line all the time.

A basic frame
So lets get a frame in here already. We define a frame by opening a  tag, and as we'll be adding a fair amount to this frame, we'll have a separate closing tag. As previously mentioned, frames typically have a parent frame and ours will be no exception. Though the question arises, as this is the first frame we are making, what do we attach it to?

The game engine itself provides a frame called  which, as its name implies, acts as the main parent frame for all UI elements. This has the advantage that if a user decides to change the scale of their UI, all frames attached to  will immediately be scaled as well without us having to do a thing.

Lastly, we'll want to give a name to our frame. We can define a frame without a name, but that would make it rather difficult to find and use later. When the game creates this frame, it will create a global variable with this name to hold our frame.

Knowing this, we can add the following between the opening and closing  tags in our XML file:

Note how the  and   attributes are used in the   tag to set the frame's name and parent respectively. The game engine will normally show any frame it creates by default. If we wanted it hidden, we could also add the  attribute and give it a value of.

The above is all we really need to define a frame. It's rather devoid of content, but it is a fully functioning frame. As we will be setting text and other things on this frame, we should also give it a size. We do this by adding a  tag to our frame definition like this:

Note the use of the  and   tags, as well as the   and   attributes in the   tag. This tells the game that we want our frame to be 200 pixels horizontally and 26 pixels vertically.

Anchoring the frame
Now that we've got a size for our frame, we'll also want to place it somewhere on screen. This however introduces a bit of a problem.

Our frame has a specific size and we need to place it on a screen which also has a size (whatever your screen resolution is set to). But we can't just say we want to draw the frame at coordinates (100, 200) because the game engine doesn't know if it should start drawing from the top-left corner of the frame, or the bottom-right, or the middle of the frame or some other position. In other words, which of the 200 by 26 pixels of our frame is the one to be drawn at said coordinates? To make matters even worse, those coordinates specify what exactly? Is it from the top-left corner of the screen? the bottom-right? some other position perhaps? To solve this, we introduce the concept of anchors.

Anchors are the means by which we can tell the game engine exactly how to position our objects (be it a frame, texture, button, or some other thing). Anchors have three important attributes named,   and. The  attribute specifies the name of some object that will serve as the starting point for any coordinates we give. The  and   attributes need a little more explaining.

Effectively, the  attribute specifies some location on our object when positioning it. The following diagram shows the values for  and the location on the object they refer to:

The  uses these same values and refer to the same positions, but on the object specified by the   attribute. This then allows us to easily align one object with another. But what about getting finer control over the position? Anchors also allow us to optionally give an offset in order to fine tune the position of an object in both the X and Y coordinates (horizontal and vertical positions).

Lets put our frame 50 pixels down from the top of the screen, and centered horizontally. Since the frame UIParent encompasses the entire screen, we can use it as the object we will align our frame to. What we wish to accomplish can be seen diagramatically like this:

Note that even though UIParent also happens to be our frame's parent, it doesn't need to be the object we anchor our frame to.

Given the above diagram, we'll want a  value of , and a   value also of   and a   value of. We'll also want offsets of 0 in the horizontal direction and 50 in the vertical direction (positive values go down).

To specifiy all this in our XML, we need an  tag which itself needs to be inside an   tag (note the spelling). This last is to define a list of anchor points, but we'll only have one here. So modify the frame definition like this:

Note how the offsets are defined much like we did for the size of the frame.

Adding some text
So far we've got a frame and given it a size and placed it on screen. All this work and we still don't even have it displaying anything. Since we want to have this frame display the amount of Lua memory in use, we'll obviously need to display some text so lets add that as the first displayable part of our frame.

To add text we need a FontString object. This will actually be a sub-object that we'll attach to our frame. Since there are many details to FontStrings that need to be specified but are the same for most FontStrings we would want to create, this is a good time to introduce the concept of virtual objects and inheritance.

A virtual object is an object that is pre-defined, completely or partially, but is not loaded by the game. Instead, the game uses these objects as templates for other object definitions. Objects we define based on these virtual objects inherit all definitions from the virtual object, and then any definitions we create in our real object will override the ones in the virtual object. This then allows us to re-use some definitions without having to re-type every detail of the object.

As mentioned, FontStrings are good examples of virtual objects as the game already has several of these defined. So we can then re-use these objects and simply make the changes we require. This also has the advantage of giving a more standardized look to our text.

This is what our FontString will look like:

The first thing to note here is the use of the  tag to create the FontString itself much as we did for our frame. Note how the two attributes are used. Let's deal with the second attribute first.

The  attribute tells the game that we want to have our FontString use the same definitions as in the virtual object given. In this case, the virtual object is called. If you have a FDB extractor program, use it to open the file  and extract the file   (replace the "enus" part of the filename with whatever locale you wish). Once extracted, open this file in a text editor and you will find the definitions for all the virtual FontString objects the game defines. You will note that many of them also inherit from another definition also in this same file. To get the full definition, you will need to follow the trail of  back to the first one that doesn't have an   attribute (in this file, this is typically  ).

The  attribute here is a little special. The value  here will have special meaning in this case. The  part will actually get replaced by the game with the name of the parent object for this FontString. Since it will be a sub-object of our frame, and our frame is called, the FontString's name will actually become. This is an important thing to know.

Finally, note how the anchor is being defined here. Much like for our frame, we have an  tag inside an   tag and in this case we are using the   of both the FontString and the object we are aligning to. However, there is no definition for which object we are aligning with, nor are there any offsets defined. When the game sees this, it will simply assume that the object being aligned to is the parent object of this one. Therefore, it will anchor itself to our frame, which is what we want. As for the missing offset values, they will simply be assumed to be 0 when they aren't given.

All we need to do now is to set the actual text to be displayed, and attach it to our frame. The first is rather simple. We can simply add a  attribute to our   tag and set its value to the text we want. We'll see later how to change it, but for now we'll simply use some static text. Attaching it to our frame is a little more complex however, and requires the introduction of the layers concept.

Since a frame is effectively just an abstract construct to which we attach other things, we need a way to tell the game engine which objects should be drawn above or below other objects attached to the same frame. Layers are simply a way to set this order. Multiple objects can be given in each layer and multiple layers can also be defined. It should be noted here that layers are for frame elements such as textures and FontStrings, but not frames or frame derived objects such as buttons. We'll see later how those are handled.

So given our FontString definition above, we can modify our frame definition as follows:

The  tag here defines the list of all layers, while the   tag allows us to set each sub-object to include in this layer. Note that multiple objects can be added to each layer and multiple layers can be defined in the  tag. Notice the  attribute in the   tag. This sets at which level we want the objects in this layer to be drawn at. Valid values for the  attribute are, in increasing priority:


 * "BACKGROUND"
 * "BORDER"
 * "ARTWORK"
 * "OVERLAY"
 * "HIGHLIGHT"

Higher values mean that they will be drawn above objects in lower priority layer levels.

Finally, the  attribute of the   tag has been set to some text for us to see.

Enter the code snippet
When the text for the FontString was set above, we could have specified a variable name instead of the text directly, but as we'll want to be updating this text with the actual Lua memory usage values, we'll need to reset it anyway so we can consider the text we set to only be a place holder. However, updating the text itself is going to require calls to some Lua code. This is where the code snippets come into play.

Code snippets are simply small pieces of Lua script that are attached to frames and executed by the game when certain game conditions occur. If a code snippet for a given condition is present, the game will run that small piece of code, otherwise the game ignores the frame for that condition. Though some rather complex pieces of code could be used as code snippets, it is best to keep these code snippets small. If more complex functions are needed, we can always create a Lua function to handle it, then have a small code snippet to call this Lua function. Obviously then, these code snippets are how we can get the game to call functions in an addon.

There are several types of conditions that we can attach code snippets to. Here is a table of just a few of the more common ones:

One thing not shown in the above table is that some of these code snippet points also provide extra information in specific Lua variables. For instance, the  snippet has access to a string variable called   that contains the name of the event that has occurred. The  snippet can access a variable called   which contains the amount of time, in seconds, since the game last called this   snippet. and  have access to a string variable called   which contains the name of the button that was pressed or released respectively.

So for our example add-on we'll use the  snippet to update our text, and we'll use the   snippet to set the values up for the first time.

To define a code snippet, we open a  tag and within it, open a tag with the name of the snippet we need. Within each of these we can put any Lua code we want, but as mentioned, it is best to keep these snippets small. The Lua functions we'll create to do the real work will actually reside in our  file. Though they will likely be small enough that we could have defined them directly in the snippet, doing it this way demonstrates how the frame, and the game, ends up calling the functions we want.

We'll define two functions in our Lua file to handle the actual work. The first we'll call  and the second we'll call   (real original names, yes). Each of these functions will do what their names actually imply. Knowing all this, we can create the code snippets like this:

The things to pay attention to here is how all the code snippets are defined within the  tag and how the snippet itself is defined for each of the snippets. Further, notice the use of the  variable in the   code snippet. Again this variable is pre-defined by the game and appropriately set when it executes this code snippet. It may or may not be valid for other code snippets so only use it with. We'll use this to allow us to update the displayed text only every couple of seconds or so.

Here is the version of the complete XML file so far:

Make sure no errors are in the file, then save it and open up. It's time to write up those functions.

Adding the Lua functions
For the Lua file, we simply need to define the two functions that are called from our frame's code snippets. As they will both be doing mostly the same task, we'll create a third helper function for both of these.

To start, we should define a local variable to hold all our functions and variables, but as we'll want to call these functions from outside the Lua file, namely our frame defined in the XML, we'll also need to make sure it is visible from global space. This does seem to be a convoluted way to do things since we could simply define it in global space to begin with and be done with it, but due to the way Lua works, this will actually give us extra execution speed. Here is what we need, with a comment header for the file as well.

Now to define the functions themselves. First up will be the helper function. This function will simply set the text for the FontString on our frame. As it is only for use internally, we'll declare it as a local function.

Notice how the text to the FontString is being set here. Recall that  is the actual name of the FontString attached to the frame we defined in the XML file. The  method of a FontString accepts a string to be used as the actual text and optionally also red, green and blue color values (in our case, this will simply make white). The  call merely creates a string for us where the   and   will get replaced with the value in the variables   and   respectively.

Now to define the OnLoad handler function. As this function will get called once the frame has been created, we'll use it to intialize our add-on and also make sure the text on the FontString is correct.

Here we get the current amount of memory used by Lua with a call to the  function and save it in our local variable. Then we set the text of the FontString using the helper function we just created. As this is for initializing the add-on, the same value is passed as both parameters to our helper function. Lastly, we initialize another variable to 0. This last will be used to keep track of how much time has elapsed since we last updated the FontString text in the OnUpdate handler.

Finally, we come to our OnUpdate handler. The function is not much more complex than the OnLoad handler, but we only want to update the text every couple of seconds or so. This way we aren't wasting too much time setting the text when nothing really interesting is going on. Here's the code:

The first thing this function does is increment the time tracking variable, then checks to see if at least two seconds have elapsed. If so, it gets the current Lua memory usage in the same way we did in the OnLoad handler. It then calls our helper function to set the FontString text with the current and previous memory usage values. Finally it saves the current memory usage as the previous value (for the next time we update the text) and then resets our timer counter to zero.

Save the file and try the add-on out.

Continue to Guide to XML Frames - Part 2