Graphical User Interface
The GUI in Orxonox is administered with CEGUI. We use the GUI for interactions with the user in shops, Questsystem or parts of the HUD and of course the main menu.
The framework consists of various elements, putting all necessary elements together for a functioning GUI. Those elements are basically the GUIManager, Lua-scripts, layouts and the corresponding graphics.
Written in C++ the GUIManager manages all the GUIs in Orxonox and represents the interface to CEGUI. Connected to Lua via a tolua++ interface it is able to load Lua-scripts and connect C++-functions to Lua and vice versa.
To use the GUIManager in C++-code you can call it easily as it is a singleton:
#include "gui/GUIManager.h" ... GUIManager guiMan = GUIManager::getInstance(); GUIManager* guiManPtr = GUIManager::getInstancePtr();
Find out more about the GUIManager's methods in the Doxygen-Documentation
To access C++-code in Lua you have to mark them. You can see how this is done on this page. Afterwards calling a method of a C++-class you can proceed as below (— denote commentaries in Lua)
-- using namespace orxonox and calling method "getInstance()" of GUIManager guiman = orxonox.GUIManager:getInstance()
Lua-scripts are written in Lua and implement the functionalities of CEGUI like interactivity. Each GUI needs a separate Lua-script which will be loaded by the main script. Our implementation ensures that a GUI cannot be loaded more than once.
If you want to create a new GUI you need to create a lua file with the following header. Of course you would change mainmenu to the name of your GUI. The name of the GUI and the filename should be the same.
gui = require("gui") local P = gui:new() --inherit everything from the gui package mainmenu = P P.filename = "mainmenu" P.layoutString = "MainMenu.layout" ... return mainmenu
Specify events in your GUI as follows:
-- events for mainmenu function P.button_quit_clicked(e) ... -- do something end
If you want to execute code in Lua just when the GUI is loading (for instance manipulating the loaded elements) you can write an init function which will automatically executed when the GUI is loading.
To load a GUI from inside Orxonox, you can just call the showGUI()-function of the GUIManager with the file name of your Lua-script:
// shows the GUI called "mainmenu" and loads it beforehand if necessary GUIManager::getInstance().showGUI("mainmenu");
Images are loaded into so called imagesets. As the name suggests, you can group several images into one single imageset. This can be used for instance when defining "active", "hover", "clicked" and "inactive" state of a button. You'd load just one image file into the imageset, but define various images from that imageset.
Imageset files are written in XML and very easy to use. To be able to use the specified images though, you need to include the imageset into a scheme file. Schemes are explicated in the next section.
To add an image file to a imageset and defining one or more images from this imageset this example code should help:
<Imageset Name="MainMenuBackground" Imagefile="main_menu_1.jpg" NativeHorzRes="1400" NativeVertRes="1050" AutoScaled="true"> <Image Name="Background" XPos="0" YPos="0" Width="1400" Height="1050"/> <!-- define more images similar to the line above --> </Imageset>
Schemes define a certain style and provide the Lua-script with the necessary resources. It is written in XML. At the moment we just use the standard-scheme for the window look and for our own images (OrxonoxGUIScheme.scheme). Since this is included in the main script, you just have to add your new imageset to the scheme and can forget about it.
Layouts define the structure of the GUI. It defines the positions of the various elements and their size and behavior. You can also add events to the elements of the GUI and process the event in the Lua-script. Everything is written in XML, but you can access every parameter of each element in the layout. The layout however reaches its limits soon, but it is advised to define as much as possible in the layout.
Every GUI-element is a window. The underlying class-structure inherits everything from a basic window element. Buttons and text input elements implement various new parameters and functions. They also need different kinds of images. At the moment we advise to use a predefined look for our GUI, namely the TaharezLook. However this may change in the future, when we want to define our own looks. Check out the parameters and functions of each element in the layouts already in the media directory or in the CEGUI-API. The API is written for C++, but you can access the same function in a similar fashion, using Lua or XML.
Every element in CEGUI is a window. So all elements have the following properties. You may want to disable or enable certain elements to render them unresponsive to user input. Some elements like buttons do change their look, when you change their state. Every element is enabled by default. To disable an element from the beginning you can add this line to your layout:
<Property Name="Disabled" Value="true"/>
Please note, that there is no property called Enabled. So trying to set it to false will not work. In Lua however you can either enable or disable a window simply like this:
win = windowManager:createWindow("TaharezLook/Button", "test") if b_disableNewButtons == false then win:enable() else win:disable() end
Listbox is a box where you have a list of ListboxItems? which you can choose from. See this example on how to create a Listbox in Lua:
list = windowManager:createWindow("TaharezLook/Listbox", "listbox") item = CEGUI.createListboxTextItem("Text") CEGUI.toListbox(list):addItem(item)
To be able to choose an item in the Listbox use
The selected item is received when calling
If nothing is chosen, the function returns nil.
To react on events use
- ListItemsChanged? - For changed content of the list
- ItemSelectionChanged? - If the selection of an item changed
Other events are easy to figure out from their documented event name. Just drop the Event and you're good to go.