Jump to content

Reading UI & HUD XML files


Recommended Posts

1. XML basics

XML, extensible markup language, is a meta-language that describes information by breaking it down into smaller elements using tags: <>. In itself, it does nothing. It just helps organize data.

XML is often described in contrast to HTML - after all, a lot of its practical applications (and most guides) are related to web design. While HTML displays data, focusing on how it's supposed to look, XML describes the information, telling us what it consists of.

If we ran an online shop, we probably hooked up our site to a database that holds everything there is to say about the different items in our inventory. Let's assume this was done in xml, and remember what kind of shop we'd probably run:

<sex_store_inventory>
    <toys>
        <name>Jack Rabbit</name>
        <price>$59</price>
        <description>Ten-Speed Dual Action Vibrator</description>
    </toys>
    
    <toys>
        <name>Magik Mike</name>
        <price>$99</price>
        <description>7-Function Dual Action Vibrator with Rotating Ball Bearings</description>
    </toys>
    
    <gels>
        <name>Booty Eaze</name>
        <price>$15</price>
        <description>Anal soothing gel</description>
    </gels>
</sex_store_inventory>

In itself, listing our inventory in XML doesn't do anything, except wrap up the information in a plain-text format, divided in different elements according to the tags, ready to be used by software. <price> doesn't mean diddley to a browser, so our site software would need to be coded to use that intel and display it according to how we'd like that to happen. Maybe something like:

 

<appealing images on the left here>                                          Jack Rabbit                        $59

                                                                                                                                       Ten-Speed Dual Action Vibrator
                        
<image>                                                                                 Magik Mike                         $99
                                                                                                                                       7-Function Dual Action Vibrator with Rotating Ball Bearings

<image>                                                                                 Booty Eaze                        $15
                                                                                                                                      Anal Soothing Gel

    

Or completely differently, who cares even. That's html's job.

 

What's important is that, broken down to basic elements, the information is easily shared among different software and different versions approaching the display of it entirely differently, without the raw data becoming unusable, even if some software is coded not to use all the data, or when new intel is added. This is why it's called 'extensible'.

 

If there were some sort of safety test for vibrators or some kind of rating that they passed, we could add that intel in new tags
<FancyRating>yes</FancyRating>
and the software wouldn't need updating in order to continue displaying the intel it already displayed before.

 

 

2. The rules of XML
 

In XML you use tags to pretty much devise your own code language. It's up to you (or in our case Bethesda) what the tags mean. There are only a few pre-defined bits that simply needed special treatment because certain characters such as < and > are taken up by the language, ie they're already used for tags. Instead, we'd use < (lesser than) > (greater than) &quote; (quotation mark) and & (ampersand). Those are called entities, shortcuts really, and Bethesda uses entities of its own to refer to elements that are probably hardcoded. Eg boolean elements have values of &true; or &false.

 

Because it's not really a language in its own right there's not much to remember when you read xml that isn't going to be a direct result of Beth's choices. Just that:

 

a) All elements must be closed with a closing tag

 <tag>content</tag>

or be a self-closing empty-element tag:

    <tag/>

The latter is usually used in combination with attributes, see below.

 

 

b ) Tags are case-sensitive and must be properly nested:

<Tag> content </tag> : wrong
<tag1><tag2> content </tag1></tag2> : wrong
<tag1><Tag2> content </Tag2></tag1> : correctamundo

c) all documents need to have a root tag: every document's structure starts with the one tag holding everything else.

<A>
    <B>
    </B>
</A>
<C>
</C>

is incorrect because there are 2 elements, A & C, at root level.

<A>
    <B>
        <D>
        </D>
    </B>
    <C>
    </C>
</A>

is correct.

The relationship between different elements of an xml document is often described as a family tree. Elements on the same level of the hierarchy are called 'siblings'. An element containing another is the 'parent' to it, and the other one's its 'child'. Grandparents and grandchildren exist too. However, procreation happens asexually, what else is new, so there are no spouses or anything. ?

 

 

d) some information about the element can be parked inside the tag itself rather than in a sub-element. When this is done, it's called an attribute. For instance, an element defined as text below is identified by a singular name using an attribute:

<text name="NameOfTextElement">
</text>

Information that's parked in an attribute tends to be that type of meta-information, something unique to the element that wouldn't benefit much from being listed as a sub-element.

 

e) you can add a comment that won't be processed like this:

<!-- mycomment -->

3. XML in Bethesda games: a schema

 

 

Recap: Beth's pre-skyrim Gamebryo games have their menus and HUD components organized in elements inside XML documents. The elements and their hierarchy are translated into what to display on-screen by the game's own XML parser. For that, it applies meaning to elements, the tags and what's between them. XML supplies a loose syntax, Bethesda brought the vocab. And didn't quite publish a dictionary, so that could pose a problem for modding.

 

That type of dictionary, telling us which tags in an XML structure are valid and meaningful, is what is called an XML schema. Luckily for us, some clever people on the CS wiki figured most of that out for us when it came to Oblivion. Of course we should always be cautious not to automatically assume that everything that worked in Oblivion does in FO3 or FNV, but I'll gladly follow their structure.

 

It divides Bethesda's xml elements in roughly 3 major types: object elements, property elements, and operator elements. You can see them all in this excerpt from stats_menu.xml, lines 1415-1420:

<image name="stats_hunger_meter">
                    <locus> &true; </locus>
                    <filename> Interface\Stats\rad_meter_bracket.dds </filename>
                    <zoom>
                        <copy src="parent()" trait="zoom"/>
                    </zoom>
...
</image>                    

The main element here declares that a new image component is added to the stats menu. These are what are called object elements, which introduce new objects to the menu or hud. As a matter of course, these are immediately given a name with the name attribute, so that operator elements and NVSE functions can refer to them.

 

One level down, you can see that several things about this new component need specifying, such as which texture it uses (the <filename> tag), and its zoom percentage. Other properties included the dimensions and the position of the object element. Elements specifying the properties of object elements... are called property elements. Also known as traits.

 

A lot of times the content of a property element can be an absolute value, either numeric or a string such as that filepath. However, these values can also be calculated during the game session, copied from the properties of other object elements and/or manipulated by mathematical and conditional elements. In the example above, the image's zoom percentage is copied from that of its own parent. Elements that perform such 'live' operations on property elements are called operator elements. They often involve the use of the src and trait attributes, in order to refer to another property. Src will most likely refer to an object element or something global, while 'trait' will refer to the property.

 

There are cases of elements that fall a little outside of this overall division. One is the <include> element, which you can spot all over the vanilla files, inserting code from other documents, the obvious advantage there being that you can use the same code all over without having to type it again all the time:

        <image name="stats_headline_h1">
            <include src="line.xml"/>
       </image>

While we'll give you the rundown on the most commonly used object, property & operator elements in a minute, it's important to also point out that many documents may contain custom property elements. They're marked that way by starting them with an underscore. In themselves they're a mystery to the parser, but they can be referred to by name by operators and NVSE functions, and have operators as children, so they're good at holding values and doing intermediate calculations, in order to avoid longer formulas, and at interacting with your mod's scripts.

 

Eg, again from stats_menu:

<_meter_height> 38 </_meter_height>                                              <!-- line 26 -->
<height> <copy src="StatsMenu" trait="_meter_height"/> </height>                 <!-- various lines --> 

3.1. Object Elements

 

<rect> defines a rectangular region on the screen. In itself it won't be visible, but its own properties affect any children it has. In the example below, the text element that is a child to the rectangle element inherits the <systemcolor> property.

    <rect name="SneakMeter">
        <id> &noglow_branch; </id>
        <systemcolor>&hudmain;</systemcolor>
        <width> 356 </width>
        <height> 34 </height>

        <text name="sneak_nif">
            <width>128</width>
            <height>128</height>
            <justify>&center;</justify>
        </text>
    </rect>

<text>, as you can imagine, defines a text component

 

<image> defines a rectangular area that is to be filled with a texture.

            <image name="filled_checkbox">
                <visible>&false;</visible>
                <alpha>0</alpha>
                <filename>Interface\Shared\Marker\glow_square_filled_small.dds</filename>
                <texatlas> Interface\InterfaceShared.tai </texatlas>
                <width>26</width>
                <height>26</height>
                <x>-20</x>
                <y>3</y>
            </image>

<nif> defines an animation, and is used in loading_menu.xml, as well as for the breath meter in the hud:

    <nif name="BreathMeter">
        <filename>Interface\HUD\AirTimer01.NIF</filename>
        <animation>Forward</animation>
        <visible>&false;</visible>
        <alpha>0</alpha>
        <width>64</width>
        <height>64</height>
        <systemcolor>&hudmain;</systemcolor>
    </nif>

<menu> is the root element of menu-related xml files.

<menu name="HUDMainMenu">
    <class> &HUDMainMenu; </class>
    <stackingtype> &does_not_stack; </stackingtype>
    <visible>&false;</visible>
    ... and so on
</menu>

Other object elements encountered in vanilla include <hotrect> and <template>. As an object element, <template> probably serves a similar function as custom property elements do: holding intel that can be re-used elsewhere. That would make sense. Unsure about the difference between <rect> and <hotrect> (see stats_menu.xml).

        <template name="stats_list_template">
            <hotrect name="stats_list_template_item">
                <include src="list_box_template.xml"/>

3.2. Property Elements

 

Property elements, or traits, define the properties of their parent elements. They can have literal values (numbers, strings, entities such as &true; or &false;), or consist of formulas that use operator elements.

<width> 450 </width>            vs                 <width> <copy src="screen()" trait="width" />

If an element contains 2 or more properties of the same type, the last one wins. If no property is defined in a context where it would be applicable, the standard value will be used, usually 0 or empty string. In-game, properties get updated if any of their properties change as a result of an engine calculation or a script command. For instance, changing a property with SetUIFloat or SetUIString will immediately reevaluate all properties that use it.

 

a. size and position

 

<x> and <y> define the position of the parent element on the x & y axis on the screen

<width> and <height> should be self-explanatory

<locus> is a boolean element. If &true; the x/y positioning of the element's children will be relative to that of the element, if not it will be absolute.

 

b. rendering

 

<visible> is a boolean that toggles on or off the display of an element, as well as that of its children. A hidden element can't be clicked or moused over but can still be activated through script.

<alpha> is a numeric element that determines its parent's transparency, values range from 0 to 255 (normal, full visibility)

<depth> is a numeric element that determines precedence for overlapping elements. The element with the higher value will be drawn on top. By default, children have higher depth than parents.

<clips> is a boolean that makes sure that if the parent's <clipwindow> property is true, the child element will be hidden if it's outside of the parent's diemensions.

<systemcolor> takes entities, mostly &hudmain; which stands for the hud's main, 'pipboy' color

 

c. clicking & mousing over

 

<target> is a boolean element that determines if an element (rect or image) will react to player input. If true, the mouseover property will be set accordingly by the engine and if the element has an <id> property, clicking on it will set it to 'clicked' and play the specified clicksound.

<clicked> is a numeric element that's set to 1 by the engine for a single frame after the element is clicked by the mouse.

<clicksound> is a numeric element that determines which click sound effect is played when the element is clicked.

<mouseover> is another numeric element that is automatically set to 1 by the game engine when the element has mouse focus. It is set to 0 otherwise.

 

d. properties unique to image elements

 

<filename> specifies the filepath to the texture that the element will display, relative to the Data\Textures folder.

<zoom> is a numeric element that specifies the zoom percentage. If larger than 100, it will magnify the source texture. If 0, it will hide the image. If -1, the image will be resized to fit the element's width and height instead of becoming cropped.

<filewidth>, <fileheight> are read-only elements, set by the game engine to the actual width and height of the loaded texture (in pixels), after zoom has been applied. If zoom is -1, the value is 0.

<tile> is a boolean element, if true and the width or height of the element is larger than the texture, 2 or more of the texture will be stacked together in a single image.

<cropx>, <cropy> specifies the point of the texture that will be placed at the upper left-hand corner of the image. See here for an example.

<texatlas> seems to refer to a .tai file, which unsurprisingly is a 'texture atlas', a file holding several textures.

 

e. properties unique to text elements

 

<string> contains the text that is to be displayed.

<red>, <green> and <blue> are numeric elements that you can use to specify the color of the text. Ranges from 0 to 255.  (These also work on images!)

<font> is a numeric element that stipulates which font is to be used according to the fonts listed in fallout.ini. If missing or invalid, it'll default to font 1.

<justify> is an element that specifies where the text begins relative to the element's x coordinate. Values are "&left;", "&center;" and "&right;".

<wrapwidth> is the maximum width in pixels of the element. If the text exceeds this width it's split into multiple lines.

<wraplines> is the maximum number of lines displayed.

 

See here for potential advanced use of the elements <IsHTML>, <PageNum> and <PageCount>, which should allow the display of text divided in pages.

 

f. properties unique to menu elements

 

<class> specifies which internal menu class to use for handling in- and output to the menu. The values can be numeric and match the codes used by MenuMode, but are usually specified as entities matching the menu name, such as &HUDMainMenu; or &StatsMenu;   If a value is entered that doesn't correspond to a menu class, the menu will open but not be updated or accept input.

<stackingtype> determines whether or not the menu blocks the use of other menus or the gameplay controls when it's open. Most do block such interaction and are marked as "&no_click_past;".

<menufade> specifies the duration in seconds of the fade in/out effect when the menu is opened and closed. A menu doesn't update or accept input while it's fading.

 

g. general & misc

 

<id> is supposed to be somewhat related to a menu's <class> tag, in that it specififes which part of the menu's own class system the element corresponds to for the purpose of updating and accepting player input. The examples on the Oblivion schema page are limited to menu types unique to that game, and it is unclear just how <id> functions in the context of various Fallout menus.

 

<user#> : element types starting with user aren't normally part of the xml schema but can be recognized by specific menu classes. Like <id>, it seems their significance very much depends on the menu they're in. According to the talk page here, they seem to be meant as some sort of placeholders to be used instead of referring to a menu structure several levels down, which might be subject to modding.

 

 

Other unexplained property elements are listed here.

 

 

 

3.3. Operator Elements

 

a. how they work

 

Operators perform certain operations on property elements, using either literal values

<rect>                       <!--object-->
  <x>                        <!--property-->
     <copy> 10 </copy>       <!-- operator: 'copy' is necessary if you'll perform further operations --> 
     <add> 5 </add>          <!--operator-->
  </x>
</rect>

or other properties as their second operand, with the 'src' and 'trait' attributes in a self-closing tag:

<rect name="thiselement">
  <x>
      <copy> 10 </copy>
      <add src="anotherelement" trait="y" />
  </x>
</rect>

Multiple operations are possible on the same property, and they are performed from top to bottom. If you need a different precedence instead, you can nest them:

<rect name="thiselement">
    <x>
         <copy> 10 </copy>
         <add src="anotherelement" trait="y" />
         <mul> 2 </mul>
         <add>
               <copy> 10 </copy>
               <div src="anotherelement" trait="x" />
         </add>
   </x>
</rect>

b. possible values for 'src'

 

The most direct way of referring to another property to perform an operation with is to simply state its name.

<rect name="firstrect">
   <x> 10 </x>
</rect>

<image name="firstimage">
   <x>
      <copy src="firstrect" trait="x" />
   </x>
</image>

However, there are also 'relative' ways to refer to other properties, using values for 'src' that include me, parent, sibling(name), and child(name):

<y> <copy src="me()" trait="x" /> </y>

sets an element's y position to the same as its x position

<x>

   <copy src="parent()" trait="x" />

</x>

sets an element's x position to that of its parent

<width>

   <copy src="sibling(siblingsname)" trait="width" />

</width>

sets an element's width to that of a specified sibling. If the name of the sibling's omitted, it defaults to the sibling defined directly before it.

Child follows the same syntax in that you need to specify a name, but it will also find grandchildren and below. If multiple children, grandchildren etc exist with the same name, the last one specified in the xml will be chosen.

 

Lastly, src can also refer to certain global properties, most notably by using "screen()" and "io()". In the example below, a hud element is positioned at the far right of the screen, by setting its x position to the width of "screen()", minus the element's own width:

<image name="thisimage">
   <width> 300 </width>
   <x>
       <copy src="screen()" trait="width" />
       <sub src="me()" trait="width" />
   </x>
</image>

io() is probably an abbreviation for input/output, as it tends to serve as a means of communication between the xml parser and the game's geck scripts. Properties copied from io can be set in geck script with SetUIFloat and SetUIString. Pretty important, if you plan to toggle elements or position them using geck script and possibly MCM settings.

    <visible>
        <copy src="io()" trait="_MyModVisible" />
    </visible>

means that the HUD component described by this element will be visible, if the custom property "_MyModVisible" has been toggled on with SetUIFloat in my script:

SetUIFloat "HudMainMenu\_MyModVisible" 1

c. common operators

 

Math operators:

<add>, <sub>, <mul> and <div> should be self-explanatory. Also available are <mod> (modulus) and <rand> (random number between 0 and the contents of <rand> </rand>)

 

Logical operators, all returning the entities &true; (standing for the number 2), or &false; (1, or any other number):

<onlyif> and <onlyifnot> condition the element before them.

<systemcolor>
    <copy> &hudmain; </copy>
    <onlyifnot>
        <copy src="io()" trait="_MyModAltColorTrait" />
        <eq> 1 </eq>                              <!-- superfluous, really -->
    </onlyif>
</systemcolor>

<and>, <or>, and <not> should be fairly familiar.

When it comes to comparing numbers to values, we have <lt> (lesser than), <lte> (lesser than or equal to), <gt> (greater than), <gte>, <eq> (equals), and <neq> (not equal).

<min> and <max> set the property value to, respectively, the minimum or maximum of itself and what's between the tag.

<x>
   <copy src="parent()" trait="x" />
   <min> 200 </min>                             <!-- will be 200 or less -->
</x>

4. Conclusion

 

All this was ever meant to be was a guide in how to read UI-related xml files. Even understanding xml syntax and most of Beth's vocab, it still takes some dogged perseverance to make sense of the more complicated menus, but at least it should give you a chance. Reading is obviously a prerequisite for ever hoping to write one, and that'll be the focus of another tutorial.

Link to comment

Having made two functional ASX menus for Oblivion, this is a good introduction.

A few useful resources (for Oblivion but I suspect much of it may be generally applicable)

http://cs.elderscrolls.com/index.php?title=Category:Oblivion_XML

The MenuQue plugin documentation (http://www.nexusmods.com/oblivion/mods/32200/?)

and this actual demo of using some of the above! (http://www.nexusmods.com/oblivion/mods/45877/?)

 

To expand on some of the questions raised with answers from the wiki:-

There is a discussion if Id, Locus and Stackingtype here: http://cs.elderscrolls.com/index.php?title=Property_Element

 

 

 

Link to comment

I'll check that out, thanks Symon!

Following up on the reading, I plan to write a few things about writing HUD & UI and obviously welcome any input along the way. I'm barely even a beginner at any of this myself - I just feel like learning something from time to time. :)

Link to comment

Heh, the CS wiki does have quite a bit covered already indeed. Especially dividing it up into object, property, and operator elements seems a better way to organize things than my listing there. Once I organize the xml schema, I'll get working on a few guides like how to add a hud element like a number readout or a bar image like the arousal bars I added to Spunk, then maybe one of those navigable things like A.J. made. Build up the complexity like that. Not limited to HUD though - I'd love to be able to add a hotkey to the inventory menu, then pop up some other menu that affects the item I was hovering over. I see all the makings of that in obse.

Link to comment

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue. For more information, see our Privacy Policy & Terms of Use