-
Notifications
You must be signed in to change notification settings - Fork 113
xml_structure
title: Interface XML Structure description: Files, parse order, defines, templates, vectors, styles, options blocks and window registration published: true editor: markdown
An interface is a set of XML files, each rooted at <interface_config>, parsed as one merged document: the children of every file are appended in order and then processed together. Declaration order matters across files exactly as it does within one file, which is why skins and shared styles are parsed first (config_sample.xml, widgets_sample.xml before main_sample.xml in the sample; config.xml and widgets.xml first in the client).
Before each top-level element is handled, three text transforms run in order:
-
Feature flags:
<flag name=.../>and flat<if flags=...>/<elseif>/<else>/<endif>markers conditionally strip siblings (a preprocessor for product flavors). -
Define expansion: every
%namein every attribute is substituted (see below). -
Style merging:
style="name"attributes pull in style properties (element attributes win).
Then two passes over the top-level elements:
-
Pass 1 handles declarations:
<template>,<options>,<define>,<style>. -
Pass 2 handles content:
<root>,<group>,<instance>,<view>,<ctrl>,<vector>,<link>,<variable>,<tree>,<proc>,<anim>,<sheet_selection>,<lua>.
Unknown elements are offered to embedder-registered parser modules (this is where client-only elements like <macro> and <action_category> live; they are not part of the library).
A failed element normally warns and is skipped. The exception is <lua>, whose failure is fatal: scripts run at parse time and the interface is assumed to depend on them.
<define id="case_upper" value="2" />
<define id="menu_bg" value="w_modal.tga" />
<view type="text" case_mode="%case_upper" ... /><define> registers a textual macro: %name is replaced in every attribute of every later element. Names use [A-Za-z0-9_]; %% escapes a literal percent. An unknown %name fails the whole element that used it. value_from_code="expr" evaluates an interface expression at parse time and stores its string result.
The client's familiar
%case_upper,%case_normaletc. are defines from its config files, not built-ins. A standalone interface must declare them (0–5, see views) before use. {.is-info}
<template name="inv_slot" keep="true" id="" posparent="parent" posref="TL TL" x="0" y="0">
<group id="#id" posparent="#posparent" posref="#posref" x="#x" y="#y" w="44" h="44">
<view type="bitmap" id="back" posref="MM MM" texture="w_slot_item.tga" global_color="false" />
</group>
</template>
<instance template="inv_slot" id="b0" x="12" y="-70" />- Attributes on the
<template>element are parameter defaults;#paraminside any attribute of the template body is replaced by the instance's attribute of that name, falling back to the default. Longest name wins when parameters share prefixes; there is no escape for a literal#. - The template body is expanded inline where the
<instance>stands, then parsed as normal elements. -
keep="true"retains the template after parsing so it can be instantiated at runtime (createGroupInstancefrom code or client Lua).
<vector> is the repeated form of <instance> with $i index substitution and position chaining; syntax and semantics are in Layout.
<style style="text_button_16" type="text_button" tx_normal="w_text_button" ...
fontsize="10" shadow="true" />
<ctrl style="text_button_16" id="bt_ok" hardtext="OK" ... />A <style> records a named bag of attributes; any element carrying style="name" receives each style attribute unless it already defines it, so element attributes override the style. Styles are how the sample and client keep one skin definition per button family.
<options type="layer" name="layer0">
<param name="tx_tl" value="w_l0_tl.tga" />
<param name="header_h" value="24" />
...
</options><options> stores a named parameter map that widgets look up by name at setup: container windows read their entire skin from a layer options block (see Skinning), modal frames from a frame block (skin_modal in the shipped data), plus the fixed-name blocks container_move_opt and container_insertion_opt. herit="other" copies an existing block as the base.
Containers dereference
container_move_optunchecked. An interface with container windows but without that options block crashes on the first layout pass. Ship the global options blocks before any window XML. {.is-warning}
<root id="sample" x="0" y="0" w="800" h="600" active="true" />
...
<group type="container" id="hello" ... />
<tree node="hello"></tree>-
<root>creates (or switches to) a master group; its id gets an automaticui:prefix. Every subsequent top-level group/view/ctrl/link/tree is parented to the current master group. -
<tree node="shortname"/>registers a direct child group of the master group as a window. Only windows draw; a plain group at the root level parses fine and never renders. The name match is case-insensitive on the last id segment. - Nested
<tree><node node="child"/>...</tree>entries attach containers inside other containers; this is what builds docked rollout lists (see Windows and containers), not XML nesting of the container groups. -
Modal groups are auto-registered; no
<tree>needed. - Window stacking respects
win_priority(0–7, default 3) declared on the group.
The embedding application decides which master group is active (the sample activates ui:sample; the client runs ui:interface plus separate master groups for login and outgame).
<variable entry="UI:SAVE:CONTENT_ALPHA" type="sint32" value="255" />
<variable entry="UI:TEMP:MATRIX:$i:VAL" type="sint32" value="0" size="16" />Creates database leaves with initial values: the interface equivalent of declaring your state. Types: sint64, sint32, float/double, bool, rgba, hotspot. With size="N", $i in the path expands to N entries. If value is not a literal (doesn't start with a digit/-), it is treated as another database path to link to. Details and the fresh-database pitfalls in Database.
<proc> defines named action-handler sequences (see Action handlers and procedures); <lua file="script.lua"/> executes a script at parse time (see Lua scripting). Both are top-level elements.
<group type="...">, <view type="..."> and <ctrl type="..."> all draw from one class factory keyed by the type name; the tag only constrains what the result must be (a ctrl must be interactive, a group must be a group; a <group> with an unknown or missing type silently falls back to a plain interface_group, while views and ctrls fail). The full type-name table lives in NeL GUI; the per-widget attributes are documented in views, controls and windows.