GUI Window Tutorial

Overview
This is a step by step tutorial on how to create a custom GUI Control - a popup window which says, "Hello World". There is a tutorial for creating a custom GUI Control using the GUI Editor and another tutorial to create the same GUI Control using GUIXML. Both tutorials will result in a GUI Control that looks and behaves the same.
Prerequisites
Before going any further, you should already have worked through at least the following tutorials:
You should have HeroBlade open, and the script editor. Either create a new client-side script, or use one of your existing client-side work scripts where you can add the necessary function. Whichever script name you use, should be inserted in the place of <script-name> below.
This tutorial has been written in a "cookbook" fashion so that it is not necessary to understand each GUIControl attribute. If you want though, there is a detailed line by line explanation of the modifications, farther down on this page.
To learn more about the details of other GUIControl attributes which were not modified in this tutorial, please see the comprehensive list of Base Fields on the GUIControls page. The documentation there also includes a wealth of other information about the different Controls, including the default and potential values for each of their fields.
GUI Editor Tutorial
This tutorial will show how to create a custom GUI Control using the GUI Editor.
Create the Prototype
- In HeroBlade's HeroScript menu select GUI Editor. This will open the GUI Editor panel which lists all GUIXML Prototypes.
- Click the Create New link at the bottom of the GUI Editor panel. This should open a window. It will have four inputs on it:
- Prototype Name will be the name of the window as it appears in the GUI Editor panel.
- Description is a textual description of the purpose of the control. Do not use colons (:) in the description or it will not show up in the GUI Editor panel
- Inherit From is what base control to use to create the control.
- Class is the class (as defined in the DOM) that provides script functionality to the GUI Control. It is advisable to create one base class for each type of control that will be used, and create new classes to inherit from that as necessary. You should ensure that any classes you create for GUI Controls use the guicontrol archetype, as opposed to data. For more information on creating a class, see the Dom Editor.
- Enter "MyTestWindow" for the Prototype Name.
- Enter a description for "MyTestWindow".
- Enter "_movePanel" in the Inherit From input or select it from the GUI Control prototype selector by pressing the ellipsis button.
- The class will be automatically selected as "GUIMovePanel".
- In order to create a _movePanel using a custom Class, the class must exist in the Client DOM. Its archetype must be guicontrol, and it must have GUIMovePanel as a parent class.
- Click the Okay button. The new GUI Control will open in the GUI Editor.
- Set the new Control's size to a width of 300 (the x value) and a height of 100 (the y value), which is in pixels.
- Set the new Control's owner field to 0.
- If the owner field is left empty then by default the move panel will move its parent.
Add a Titlebar
- Select "MyTestWindow" in the GUI Control Tree View.
- Open the GUI Editor panel from the HeroScript menu.
- Type "titlebar" in the search portion of the GUI Editor panel.
- Double click on the "_titlebar" GUI Control prototype, which will add it to "MyTestWindow"'s list of children GUI Controls.
- Change the name of the _titlebar to "titlebar" by editing the name field in the Data category of the GUI Control properties.
- All GUIControls must have a name, so that they can be referenced by the GUI Engine and by HSL. The name can include spaces and different kinds of capitalization. Note that a name is usually different from the text of a control. In most cases, a Control's name is not seen by the user, it's strictly for internal use. To add something that is actually visible on the screen, this usually involves modifying a "text" field.
- Expand the list of children control's for "titlebar". It has a child control named "title" which is a "_label" type. Select it in the GUI Control Tree View and change the value of the text field to "My Test Window". Notice the title bar now displays the text "My Test Window".
- Something to note about the "title" GUIControl, it's a specialized form of Control, called
GUILabel
. The GUILabel Class inherits most of its fields from the base GUIControl, but also has a couple specialized fields, such as text. There are about a dozen different Classes that inherit from GUIControl, such asGUIRadioButton
,GUITextInputBox
,GUINumericUpDownButton
, and so forth. For a complete list of the classes, plus details on the fields of each of them, please see the section on GUIControls.
- Something to note about the "title" GUIControl, it's a specialized form of Control, called
Add a Scrollable Panel
- Add the "_scrollableparent" GUI Control prototype as a child control of "MyTestWindow".
- Change the name to "scrollable".
- Notice that the "scrollableParent" filled up the rest of the space in "MyTestWindow". That is because the dockMode is set to FILL by default. A child control must be located somewhere on the parent control. It can be positioned by specifying its exact x,y coordinates, or it can be "docked" to the parent, so it will stretch and position itself automatically. There are six dock modes:
- NONE (the default): the child control stays where you position it, in relation to the parent, at the size you tell it
- TOP: same as left, but on top. The child control stretches horizontally, overriding size.x, but respects size.y
- BOTTOM: same as top, but lower
- LEFT: the child control takes up all available space on left edge of parent. Its position will be 0,0 in respect to the parent, and then its size will stretch (or tile, etc) vertically to become the same height as the parent. The child's horizontal size won't change.
- RIGHT: same as left, but on right
- FILL: takes up as much space as possible, stretching whatever way it needs to
Save the GUI Control
- To save your changes, press the XML button on the GUI Editor Toolbar to create the GUIXML code. The language will appear in the console window, along with a message that it has been copied to the clipboard. This is purely informational, however, as your GUIXML will have been automatically written to an .xml file in the repository.
- Exit the GUI Editor by clicking on the button in the GUI Editor Toolbar that says "Close Editor".
GUI XML Tutorial
This tutorial will show how to create a custom GUI Control by writing GUIXML in the HeroScript Editor.
Create the Prototype
- Open the HeroScript Editor
- Create a new GUIXML file by going to File -> New -> GUI XML or by clicking on the New icon on the File toolbar and selection GUI XML.
- Name the file "mytestwindow" and click OK.
- To define a new GUI Control the
<createControlType>
tag is used. - Because the properties of this GUI Control are going to be modified and child GUI Controls will be added there needs to be an opening tag
<createControlType>
and a closing tag</createControlType>
.- Within this tag is where the Prototype Name, Description, Inherit From and Class is defined.
- To assign a Prototype Name add
type="MyTestWindow"
within the<createControlType>
tag. - Give the GUI Control a Description by adding
description="GUI Window Tutorial"
within the<createControlType>
tag. - To make the GUI Control Inherit From "_movePanel" add
inheritFrom="_movePanel"
within the<createControlType>
tag. - Set the new Control's owner field to 0 by adding
owner="0"
within the<createControlType>
tag.- If the owner field is left empty then by default the move panel will move its parent.
- Set the new Control's size by adding a
<size>
tag on the next line below the<createControlType>
tag. Set the size to<size x="300" y="300"/>
.
<createControlType type="MyTestWindow" description="GUI Window Tutorial" inheritFrom="_movePanel" owner="0"> <size x="300" y="100"/> </createControlType>
Add a Title Bar
- Add a "_titlebar" GUI Control as a child of "MyTestWindow" by adding a
<_titlebar>
tag on the line below the<size>
tag. - Change the name of the titlebar as is appears in the GUI Control Tree View by adding
name="titlebar"
within the<_titlebar>
tag. - Set the text of the "title" label GUI Control which is a child of "titlebar". This is done by adding the
<set>
tag on the next line below the<_titlebar>
tag. - Specify the name of the child GUI Control that is to be changed with
name="MyTestWindow.titlebar.title"
within the<set>
tag. - Specify which field is to be changed with
attribute="text"
within the<set>
tag. - Specify the value of the text field with
value="My Test Window"
within the<set>
tag.
<createControlType type="MyTestWindow" description="GUI Window Tutorial" inheritFrom="_movePanel" owner="0"> <size x="300" y="100"/> <_titlebar name="titlebar"> <set name='MyTestWindow.titlebar.title' attribute='text' value="My Test Window"/> </_titlebar> </createControlType>
Add a Scrollable Panel
- Add a "_scrollableParent" GUI Control as a child of "MyTestWindow" by adding a
<_scrollableParent>
tag on the line below the</_titlebar>
end tag. - Change the name of the scrollable parent as is appears in the GUI Control Tree View by adding
name="scrollable"
within the<_scrollableParent>
tag.
<createControlType type="MyTestWindow" description="GUI Window Tutorial" inheritFrom="_movePanel" owner="0"> <size x="300" y="100"/> <_titlebar name="titlebar"> <set name='MyTestWindow.titlebar.title' attribute='text' value="My Test Window"/> </_titlebar> <_scrollableParent name="scrollable"/> </createControlType>
Compile and Submit
- Compile the GUIXML by going to the menu Tools -> Compile or pressing the Compile button on the Compile Toolbar or using the keyboard shortcut F7.
- If the GUIXML was compiled successfully there will be text on the bottom left corner of the HeroScript Editor that reads "Valid XML" in green text.
- If the GUIXML fails to compile there will be text on the bottom left corner of the HeroScript Editor that reads "Invalid XML" in red text.
- Submit the GUIXML by going to the menu Tools -> Submit or pressing the Submit button on the Compile Toolbar or using the keyboard shortcut Shift+F7.
- Note: A script cannot be Submitted until it has been successfully compiled.
Invoking the GUI Control
Overview
The following function will create a node from the new GUIControl Prototype called "MyTestWindow".
The code in this function modifies the attributes of the subcontrols directly. It also creates an additional new GUIControl, called "myTestDataLabel", based on the "_label" prototype. The new label will have text added to it, and then be connected to the client area of MyTestWindow for display.
When the function is run, the window and associated text will appear in the center of the viewport.
Create the function
A detailed line-by-line analysis of this code is available further down on this page. For now though, it can suffice to simply type in the following, or copy/paste this function into your client-side work script:
function MakeMyTestWindow() // This creates a window GUIControl from a prototype myTestWindow as NodeRef of Class GUIControl = createNodeFromPrototype("MyTestWindow") // Always make the new window renderable in the viewport first myTestWindow.build = true // Configure the window's position in the viewport screen as Vector3 = getViewPortSize() myTestWindow.position.x = (screen.x - myTestWindow.size.x) / 2 myTestWindow.position.y = (screen.y - myTestWindow.size.y) / 2 // Create the Label where the main window text will appear myTestDataLabel as NodeRef of Class GUILabel = createNodeFromPrototype("_label") // Always make the new label renderable in the viewport first myTestDataLabel.build = true myTestDataLabel.name = "data_label" myTestDataLabel.text = "Hello World!" myTestDataLabel.autoSetHeight = true // Find the clientarea on the window control, and connect // the new text label control to it. clientArea as NodeRef of Class GUIControl = findGUIControlByName(myTestWindow, "scrollable.clientarea") add back myTestDataLabel to clientArea.children myTestDataLabel.dockMode = TOP .
- Compile and Submit the modified script
- Run the script by typing into the Console:
call <script-name> MakeMyTestWindow
- The new window should pop up with the message, "Hello World!"
- If it doesn't, please run through the above steps again, or seek help from another scripter.
- It may also be worth double-checking to ensure that you created a client-side script, and not a server one.
- Modify the script
- Close the new window control, switch back to the script editor, and try modifying various parameters in the function that was created. Then compile, submit, and run the script again, and see how changing each parameter modified the appearance of the window.
- To quickly enter the
call script
line again, just use the Up-arrow to recover the last line typed. - Note that with this kind of rapid back and forth edit/run methodology, that you may get ahead of the server. If your change didn't seem to "take", be sure to check the Console Window after you submit a script, to ensure that it was properly compiled (
Got compiled script <name>
). This may take several seconds.
- To quickly enter the
- Try making the following changes, one at a time:
- Set the MyTestWindow's
size.y
value to 400 - Change
myTestDataLabel.text
to say something different - Change the
dockMode
to another value, such as BOTTOM or RIGHT - Set
MyTestWindow
x,y position to 0,0 - Set
MyTestWindow
x,y position to 50,200 - Figure out how to change the text in the title bar of the window
- Feel free to experiment! For example, read up on all the other GUIControl fields that can be modified, and try modifying one of them to see what happens.
- Set the MyTestWindow's
- Close the new window control, switch back to the script editor, and try modifying various parameters in the function that was created. Then compile, submit, and run the script again, and see how changing each parameter modified the appearance of the window.
Detailed Explanations of the Function's Code
Detailed explanation of these steps is below:
Create the GUIControl Window Node
There are many pre-made prototypes that exist for creating a window. For example: A basic window, a scrollable window, a resizeable window, etc. For this example, the "MyTestWindow" prototype was used.
Each GUI control prototype has its own GUIXML file. The available prototypes for GUI controls are listed in the GUI Editor panel which can be opened from HeroBlade's HerScript menu.
myTestWindow as NodeRef of Class GUIControl = createNodeFromPrototype("MyTestWindow")
Make the GUIControl Renderable
When the build
flag is set to TRUE, that tells the engine that this Control is okay to render on the screen. If the Control were still in a half-finished state, this flag would probably be kept at FALSE so that the Control wouldn't be rendered yet.
myTestWindow.build = true
Position the Control on the screen
If a position is not specified, the Control will be positioned at 0,0, which means that its upper left corner will be at the far upper left of the viewport (the game screen). The position fields in this case are merely to determine the Control's starting location.
To center the Control, first determine the current size of the Viewport, with getViewPortSize()
. This returns a value in vector3 format, where the x and y values are the current width and height of the Viewport. A simple calculation between the size of the Control and the size of the Viewport (divided by two) provides the perfect location at which to position the Control.
screen as Vector3 = getViewPortSize() myTestWindow.position.x = (screen.x - myTestWindow.size.x) / 2 myTestWindow.position.y = (screen.y - myTestWindow.size.y) / 2
However, the Control could also be positioned anywhere else in the Viewport as well. For example:
myTestWindow.position.x = 300 myTestWindow.position.y = 300
Note that the position will change automatically if the user decides to drag the window around.
Create a label to hold your content
In this step, the function creates a new GUILabel Control, based on the _label
prototype.
myTestDataLabel as NodeRef of Class GUILabel = createNodeFromPrototype("_label")
Make the Label Renderable
Since "myTestDataLabel" was created by the script it's build flag needs to be toggled TRUE.
myTestDataLabel.build = true
Put some data in the new label
This code will set the name of the GUILabel and set the text that is displayed by this GUILabel.
myTestDataLabel.name = "data_label" myTestDataLabel.text = "Hello World!"
Set the size of the label
It's possible to set the size to a specific value, or it can be automatically determined. In the case of this tutorial, the size is being set automatically:
myTestDataLabel.autoSetHeight = true
This automatically make the size of the label large enough to accomodate however much text is in it.
Note: autoSetHeight does not modify the size of the font, only the size of the Control that contains the font. Though it's possible to make a larger font by scaling a Control to a larger size (which scales the font along with it), this does not look very clean. As of this writing, there is not any way to elegantly change font size or type.
Find the Client Area Control
This is a control that's already a child of myTestWindow. To manipulate it though, we need a node reference to it. So we need to "find" it on the parent, using the FindGUIControlByName function.
clientArea as NodeRef of Class GUIControl = findGUIControlByName(myTestWindow, "scrollable.clientarea")
This control defines the panel that will hold the things that you want to display. It's what's left of the window after taking account of the resize bars, title bars, etc. The clientarea fills up all the spaces between all these things.
Add the Label to the List of Client Area
This adds the new Label to the end of the list of children of clientArea. If other labels are created, they can be added in behind this one.
add back myTestDataLabel to clientArea.children