This page exists to collect information about the structure and function of the .twui.xml files used to define UI elements in Total War: Warhammer 3.
This page does not contain any guides or similar content about what you can do with this information, find those elsewhere.
All TWUI files have two main sections: the <hierarchy> tag, which defines the parent/child relationships between elements, and the <components> tag, which contains a list of definitions for individual UI Components.
GUID should be unique, usually.
The hierarchy tags are fairly self-explanatory, but there are two important things to note:
The order of elements under a parent matters.
<units_holder this="2BF7387C-AB12-0F2F-C1218D70BA83C706"> <commander_unit_card this="370200E6-29F9-F3E9-0CE701A92EABE38D"> <unit_cat_frame this="A2E6C963-1E41-5B73-E90BB28E400E4747"> <unit_category_icon this="F12647D4-2A28-6B20-AB490F093FB0FB5B"/> </unit_cat_frame> </commander_unit_card> <units this="DD3FFAC1-62DB-A97F-6CC534D4CEE1345C"> <template_unit_card this="BFE1CF9F-4548-B05E-07E381900D3EA9D8"> <unit_cat_frame this="C6F19065-8AAA-A6D8-198D229CDA1591BD"> <unit_category_icon this="81D4EFD8-88A8-CED2-4FA4C95E1D442769"/> </unit_cat_frame> </template_unit_card> </units> </units_holder>
In this example, "units_holder" is a horizontal container. The commander_unit_card element is listed first, so it will appear on the left, followed by the units element.
<header this="3D680723-45CE-B9B4-796AF87F4A7D5688"> <panel_smoke_t this="46C5826D-D9D2-9558-AD21CBBEC2C4C3CA"/> <panel_title this="3454DB8A-831C-5961-5D2FE6AA60E6BC27"> <tx_title this="4F9967C0-BF74-A403-7E14E954E1BE66C7"/> </panel_title> </header>
In this example, "header" is not a container, so panel_smoke_t will be at the back, with panel_title (and its children) overlayed ontop of it.
Context Expressions can contain information about the hierarchy
For most elements, you can alter their position in the hierarchy freely by simply cutting and pasting their tag. However, this does not always work.
Some context expressions will reference parents, and children, of an element, either in the context expressions themselves or in the user properties attached to them. Common examples of this include ButtonGroup and ContextSelectionParent, as well as properties like dynamic_child. In these cases, you will need to modify the component definitions in addition to altering the hierarchy.
Full definitions versus template implementations
Component Definitions can use different fields based on whether they are implementing a template component, or whether they are defining an entirely new component.
Template implementations can be identified by looking for the part_of_template="true" property on any component definition. They will also include a template_id property which will point to the file name of the template. When a template is called for, the game will search for a file with the specified name. It will first check the relevant UI folder for the game area (ie. ui/campaign ui/template_name.twui.xml in campaign), then check ui/templates/template_name.twui.xml.
<callbackwithcontextlist> and <callbacks_with_context>
These tags contain context callbacks. There should probably be a separate bigole page about those. If you're a starter, you want to look at features from Wh3.
Example from Wh2 feature:
<callbackwithcontextlist> <callback_with_context callback_id="AssasinationTargetCallback"/> </callbackwithcontextlist>
Example from Wh3 feature:
<callbackwithcontextlist> <callback_with_context callback_id="List" context_object_id="CcoStaticObject" context_function_id="DatabaseRecordContext("CcoRitualCategoryGroupRecord", "hellforge_unit_caps").CategoryList.Sort((cat) => Helforge.RitualCategorySortOrder(cat), true)"/> </callbackwithcontextlist>
As you can see, you know what's happening in Wh3 while Wh2 only says one single callback "AssasinationTargetCallback" which we don't know what it does.
Beep boop I haven't touched these yet.
Used to define states, which can do shit.
Even looking at these gives me a headache someone else can do this part.
When a component has a LayoutEngine attached, it functions as a list of some sort. There are horizontal ones, vertical ones, radial ones, and they have a bunch of fields you can use to modify the spacing, behaviour and appearence of the list.
- type - can be List (which is vertical), HorizontalList, or RadialList
- sizetocontent - boolean, whether the layout will automatically resize based on its children.