Difference between revisions of "Oblivion XML Reference/Traits"
Jump to navigation
Jump to search
revisions and reorganizations
imported>DavidJCobb (→Behavior: full spec) |
imported>DavidJCobb (revisions and reorganizations) |
||
Line 3: | Line 3: | ||
Due to a bug in Oblivion’s XML parser, all of a tile’s traits must precede its child tiles, or properties will malfunction unpredictably. (It appears to be possible to redefine a trait after defining child tiles if the trait was first defined before all child tiles, however.) The MenuQue mod purports to correct this bug. | Due to a bug in Oblivion’s XML parser, all of a tile’s traits must precede its child tiles, or properties will malfunction unpredictably. (It appears to be possible to redefine a trait after defining child tiles if the trait was first defined before all child tiles, however.) The MenuQue mod purports to correct this bug. | ||
Trait elements can only contain raw number values, raw string values, or [[Oblivion XML Reference/Operators|operator]] child elements. Operators can be used to compute a trait's value dynamically. | Trait elements can only contain raw number values, raw string values, or [[Oblivion XML Reference/Operators|operator]] child elements. Operators can be used to compute a trait's value dynamically. Unrecognized traits are discarded by the XML parser unless they are prefixed with an underscore. | ||
== Common == | == Common == | ||
These traits can be used on any tile. | |||
;childcount | ;childcount | ||
;child_count | ;child_count | ||
Line 20: | Line 22: | ||
== Behavior == | == Behavior == | ||
This category includes any behavior-related traits, but it also includes keyboard navigation traits. A keyboard navigation trait tells Oblivion how to respond to a specific keypress when a tile or its menu has focus. | This category includes any behavior-related traits, but it also includes keyboard navigation traits. A keyboard navigation trait tells Oblivion how to respond to a specific keypress when a tile or its menu has focus. | ||
;clickcountafter | ;clickcountafter | ||
Line 55: | Line 28: | ||
:Found in the executable. Purpose unknown. | :Found in the executable. Purpose unknown. | ||
;clicked | ;clicked | ||
:If the tile’s ''target'' trait is true and the tile has an ''id'', then clicking on the tile will set this property to 1 | :If the tile’s ''target'' trait is true and the tile has an ''id'', then clicking on the tile will set this property to 1 and then back to zero, on the same frame. | ||
;clicksound | ;clicksound | ||
:If the tile’s ''target'' trait is true and the tile has an ''id'', then clicking on the tile will play the specified sound. Values are numbers which correspond to the hardcoded editor IDs of sounds. (The sounds themselves are defined in Oblivion.esm.) The default value is zero. | :If the tile’s ''target'' trait is true and the tile has an ''id'', then clicking on the tile will play the specified sound. Values are numbers which correspond to the hardcoded editor IDs of sounds. (The sounds themselves are defined in Oblivion.esm.) The default value is zero. | ||
Line 179: | Line 152: | ||
:For list items, this trait should be set to the value that the scrollbar should be scrolled to. For list containers (always the direct parents of list items), this value should be a ref operator indicating the scrollbar whose state needs to be modified. The trait specified in the ''ref'' operator will be ignored: the executable will perform a special-case modification to the scrollbar’s ''user5'' trait in order to forcibly set the scroll position. | :For list items, this trait should be set to the value that the scrollbar should be scrolled to. For list containers (always the direct parents of list items), this value should be a ref operator indicating the scrollbar whose state needs to be modified. The trait specified in the ''ref'' operator will be ignored: the executable will perform a special-case modification to the scrollbar’s ''user5'' trait in order to forcibly set the scroll position. | ||
:It is not yet clear how the game determines that a tile is a list item that should receive the above behavior. | :It is not yet clear how the game determines that a tile is a list item that should receive the above behavior. | ||
=== Keyboard navigation handling === | |||
The process for handling a keyboard navigation trait is as follows: | |||
#The tile that had mouseover focus at the time of the navigation keypress shall be referred to as the trigger tile. The trait for the navigation keypress (e.g. xup for the up arrow key) shall be referred to as the navigation trait. | |||
#Identify a basis tile. | |||
#*If the trigger tile has the navigation trait, then it is the basis tile. | |||
#*Otherwise, search upward through the trigger tile’s ancestors, stopping at the first found tile that has the navigation trait. That found tile will be the basis tile. | |||
#If there is no basis tile, abort. | |||
#If the navigation trait uses any ''ref'' operator, then modify the specified trait on the specified other tile only if that tile is suitable. Regardless of whether the tile is targetable, stop here. | |||
#*For the purposes of this task, we use the first ''ref'' operator in the trait, ignoring hierarchy and treating all operators as a flat list. | |||
#*The exact definition of suitable is yet to be determined. However, a tile can be used if it itself is ''target''able and has an ''xdefault'' greater than -99, or if its ''xlist'' trait is set to &xlist; and it contains any ''target''able tiles with ''xdefault'' traits. | |||
#*If the trait being modified is clicked, but the target tile has an xdefault trait, then give it mouseover focus as well. | |||
#If the navigation trait uses the &first;, &last;, &prev;, or &next; entities, then search the basis tile’s siblings (in order, from first to last) for a ''visible'' and ''target''able tile with an ''xdefault'' trait (set to any value) and a suitable ''listindex'': | |||
#*For &first;, choose the sibling tile with the lowest ''listindex''. | |||
#*For &last;, choose the sibling tile with the highest ''listindex''. | |||
#*For &prev;, pick from among the sibling tiles whose ''listindex'' values are less than that of the basis tile: choose the highest ''listindex'' among those. | |||
#*For &next;, pick from among the sibling tiles whose ''listindex'' values are greater than that of the basis tile: choose the smallest ''listindex'' among those. | |||
#If no matching tile is found, then return to Step 2, treating the current basis tile as the trigger tile for that step. | |||
#If a matching tile was found, scroll it into view using the ''xscroll'' trait: assume that it is a list item tile and its parent is a list container tile. | |||
#Give the matching tile ''mouseover'' focus as appropriate. | |||
Code analysis suggests that keyboard navigation cannot be “chained:” if one tile points xup at another tile, and that other tile points xup at a third, moving up from the first tile will not bring you directly to the third. | |||
In at least some cases, using keyboard navigation to forward clicks will not also forward mouseover focus, unless ''xdefault'' is &true; or greater. This may be limited to the ''listindex''-related XML entities. | |||
Bethesda’s code comments indicate that keyboard navigation in a menu may break if no tile in the menu has initial focus. Be sure that you set an ''xdefault'' trait on any ''target''able tile. | |||
Those interested in reviewing the engine-level functionality involved can refer to subroutine <code>Tile* Tile::ResolveTraitReference(UInt32 keynavTraitID, UInt32* outTargetTraitID)</code>, located at <code>0x0058E3B0</code> in the latest version of Oblivion. That function handles Steps 1 through 7 in the above outline; Steps 4 (modifying the trait) and 8 are handled by some (all?) callers. The return value is the tile pointed to by the ref operator in Step 4, or the tile identified in Step 5; <code>*outTargetTraitID</code> is set to the trait identified by the ref operator in Step 4. | |||
To investigate the meaning of “suitable” in Step 4, examine <code>InterfaceManager::HandleNavigationKeypress</code> (located at <code>0x00580BA0</code> in the latest version of Oblivion), which calls <code>Tile::ResolveTraitReference</code> multiple times. | |||
== Box model == | == Box model == | ||
These traits relate to how tiles are sized and positioned. | |||
;clips | ;clips | ||
:If this trait is set to true and the tile has an ancestor whose ''clipwindow'' trait is true, then any part of this tile that lies outside of that ancestor’s bounds will be hidden. | :If this trait is set to true and the tile has an ancestor whose ''clipwindow'' trait is true, then any part of this tile that lies outside of that ancestor’s bounds will be hidden. | ||
Line 203: | Line 209: | ||
;width | ;width | ||
:The dimensions of the tile in pixels. | :The dimensions of the tile in pixels. | ||
:Note that these traits are not ''automatically'' set on Image tiles. If you want an Image tile to display its full image, unscaled, then you must manually set these traits to [[Oblivion XML Reference/Operators|copy]] the ''filewidth'' and ''fileheight'' traits' values. | |||
:Note that these traits cannot be set on Text tiles; instead, the executable sets them to the size of the displayed text if the text is ''visible''. | :Note that these traits cannot be set on Text tiles; instead, the executable sets them to the size of the displayed text if the text is ''visible''. | ||
;x | ;x | ||
Line 228: | Line 235: | ||
== Image == | == Image == | ||
These traits are unique to Image tiles, and generally have no effect elsewhere. | |||
;cropX | ;cropX | ||
;cropY | ;cropY | ||
Line 249: | Line 258: | ||
== Menu == | == Menu == | ||
These traits are unique to Menu tiles, and generally have no effect elsewhere. | |||
;class | ;class | ||
:Associates the menu’s root tile with a specific internal class, identified numerically. All vanilla menus have XML entities defined and available for use as shortcuts. | :Associates the menu’s root tile with a specific internal class, identified numerically. All vanilla menus have XML entities defined and available for use as shortcuts. | ||
Line 261: | Line 272: | ||
== NIF == | == NIF == | ||
These traits are unique to NIF tiles, and generally have no effect elsewhere. | |||
;animation | ;animation | ||
:The name of an animation (specifically a <code>NiControllerSequence</code>) within the NIF file. | :The name of an animation (specifically a <code>NiControllerSequence</code>) within the NIF file. | ||
Line 268: | Line 281: | ||
== Text == | == Text == | ||
These traits are unique to Text tiles, and generally have no effect elsewhere. | |||
;font | ;font | ||
:An integer between 1 and 5 indicating which font to use. The Oblivion.ini file associates each number with a font file. Numbers outside of this range will cause crashes. | :An integer between 1 and 5 indicating which font to use. The Oblivion.ini file associates each number with a font file. Numbers outside of this range will cause crashes. |