Overview of Developing Client UI
From Multiverse
| User Interface Development |
|
Overview • Managing Widgets • Event Handling • Using Widget Templates • Customizing Key Bindings • Localizing UI Text • Character Creation Framework • Minimap Component • Scripting Avatar Appearance |
| Reference |
| Tutorials |
|
Hello World • Creating a Button • Creating a Menu • Creating a Help Dialog • Using Radio Buttons |
Contents |
Running the client in standalone mode
When developing Client user interface, it is convenient to run the Client in standalone mode with the --standalone command-line option. This will start a "default" world, with some test terrain, models, and sounds, without requiring you to start a server, and the Client will display your UI.
For general information about running the Client from the command-line, see Running the Client from the Command-Line.
To develop your user interface, you modify files in the Interface\FrameXML directory of your asset repository, then run the Client with the --use_default_repository option.
So, when developing user interface, run the Client with the following command line:
MultiverseClient.exe --standalone --use_default_repository
To reload the user interface without restarting the client, use this special "slash command" within the Client:
/reloadui
Defining a theme file
Your gameworld's user interface is defined by one or more theme files with .toc extension. A theme file is a text file containing a list of user interface files to load. The client looks in the asset repository Interface/FrameXML directory for theme files.
Specify the theme file in a server script with the statement:
World.setTheme(themeFile)
For example:
World.setTheme("mars.toc")
In standalone mode, the Client loads the mars.toc theme file by default.
Sampleworld sets its theme file in multiverse/config/common/global props.py. Either edit this file and specify a different theme file, or specify an additional theme file to use in your world's config/worldname/global_props.py file.
The client loads each user interface XML file listed in the theme file in the specified order. If you do not specify a theme file, or the client cannot find the specified theme file, then it loads basic.toc.
NOTE: The Client loads the files in the specified order. So, if an interface file depends on other files, you must list the other files first.
Specifying additional theme files
If you want to create your own theme file from scratch, then use World.setTheme(). However, if you want to start with the SampleWorld theme file (mars.toc), and add your own widgets, then use World.addTheme("my.toc") to add additional theme files to mars.toc.
In general, it may be convenient to have multiple theme files, to group UI elements meaningfully. To add additional theme files, use World.addTheme(themeFile).
Example theme file
Here is an example of the contents of a theme file (mars.toc in this case). The comments at the beginning of the file have been omitted for brevity:
MvFonts.xml MvFrame.xml MvDialog.xml MvChat.xml MvItemButton.xml MvContainer.xml MvTooltip.xml MvStatus.xml MarsUnit.xml MarsPlayer.xml MarsTarget.xml MvActionButton.xml MvActionBar.xml
Sampleworld theme files
Sampleworld includes the following theme files:
-
basic.toc: Minimal theme file -
startup.toc: Character creation UI theme file. The Client loads this when it initially starts to display character creation. -
mars.toc: Full Sampleworld theme file. See Sampleworld UI Files for more information.
User interface files
Each line of the theme file specifies an XML file called a user interface file or FrameXML file (so called, because it is placed in the \Interface\FrameXML directory of an asset repository). Each FrameXML file contains exactly one <Ui> element at the top level.
Within the <Ui> element are one or more XML widget elements that represent UI controls such as buttons, text strings, edit fields, and so on. There is also a Script widget (<Script> element) that specifies a Python file to load, which is often the first element within the <Ui> element.
For example:
<Ui> <Script file="MvActionBar.py"/> <Button name="ActionBarButton" inherits="ActionButton" virtual="true"> ... </Button> ... </Ui>
XML terminology
A FrameXML file consists of XML elements, each of which has a start tag and an end tag. For example <Frame>....</Frame> is a Frame element: <Frame> is the start tag and </Frame> is the end tag of the element.
Elements have attributes, that take the form attribute-name=attribute-value. For example here is a Button widget element with "name", "text", and "hidden" attributes:
<Button name="AddButton" text="Add" hidden="false">
Here is a Color property element with attributes "r", "g", "b", and "a":
<Color r="1.0" g="1.0" b="1.0" a="1.0"/>
Almost every widget element has at least a name attribute, and most elements have other attributes as well.
Everything between an element's start and end tag is the contents of the element; The outer element is said to contain the elements within it. An empty element (one with no content) can be abbreviated, for example you can use <Anchor point="CENTER"/> instead of <Anchor point="CENTER"></Anchor>.
Types of elements
There are two types of elements in a FrameXML file:
- Widget elements declare user interface controls (widgets), such as Buttons, Frames, or Edit Boxes.
- Property elements define the properties and behaviour of the container widget. They can occur directly within widget elements or within other property elements.
Widget elements
Widget elements define UI components such as Buttons, Edit Boxes, and scrolling areas. Widget elements create Python objects with methods you can call at runtime. See Widget Reference for a complete list of widgets.
For example, the following Button widget element defines a button with the name "MyButton":
<Button name="MyButton"> <Anchors> <Anchor point="CENTER"> </Anchor> ... </Anchors> </Button>
In this example, the Anchors and Anchor property elements inside it define its properties.
The following example has two widget elements, Frame and Button,
and several property elements (Anchors, Anchor). It creates a Frame, with a Button inside it.
<Frame name="MyFrame">
<Anchors>
<Anchor point="CENTER"/>
</Anchors>
<Frames>
<Button name="MyButton">
<Anchors>
<Anchor point="CENTER"/>
</Anchors>
</Button>
</Frames>
</Frame>
For more information about how to position and work with widget elements, see Positioning and Managing UI Widgets.
Naming widgets
Every widget element (except Script) has a name attribute that creates a global Python variable of that name. You can then use this variable to call methods on that widget. For a list of methods available for widgets, see Widget Reference. A name must be unique across all XML files because the corresponding variables are global across the entire UI.
For example, consider the following:
<Frame name="MyFrame"> .. <Frames> <Button name="MyButton"> .. </Button> </Frames> </Frame>
In any Python code, you can use the variable MyFrame to refer to the frame
and MyButton to refer to the button. For example, to show the frame, call MyFrame.Show().
To disable the button, call MyButton.Disable().
You can use the special string $parent when defining the name
of a widget. At runtime, $parent is replaced with the name of
the parent widget. For example:
<Frame name="MyFrame"> .. <Frames> <Button name="$parentButton"> .. </Button> </Frames> </Frame>
This results in two global Python variables, MyFrame and MyFrameButton.
Property elements
A property element specifies one or more properties for the widget element or property element that contains it. If a property element is contained directly by a widget element, it specifies properties of that widget; if the property element is contained by another property element, it specifies or modifies properties of that property element.
For example, here is an example of a Button widget element that contains NormalText, NormalTexture, and DisabledTexture property elements:
<Button name="Friend10" text="MyFriend10" hidden="false">
<NormalText inherits="NormalFont" justifyH="LEFT" justifyV="MIDDLE">
<Color r="0.0" g="0.0" b="0.0" a="1.0"/>
</NormalText>
<NormalTexture file="Interface\ChatFrame\UI-ChatIcon-ScrollUp-Down"/>
<DisabledTexture file="Interface\ChatFrame\UI-ChatIcon-ScrollUp-Disabled"/>
...
</Button>
Notice the Color property element within the NormalText element; this property element modifies another property element. In this case, it specifies the color of the Button widget's normal text (the text it normally displays when it is not highlighted, pushed, or disabled). The NormalTexture, and DisabledTexture property elements apply directly to the button widget.
There are many different property elements, some of which are generic and apply to many widgets (for example, Anchor) and some of which are specific to one type of widget (for example, NormalText, which applies only to a Button widget).
See Property Element Reference for a complete list of property widgets.
