This tutorial shows how to use the built in User Interface of the Irrlicht Engine. It will give a brief overview and show how to create and use windows, buttons, scroll bars, static texts, and list boxes.
As always, we include the header files, and use the irrlicht namespaces. We also store a pointer to the Irrlicht device, a counter variable for changing the creation position of a window, and a pointer to a listbox.
using namespace core;
using namespace scene;
using namespace video;
using namespace io;
using namespace gui;
#ifdef _IRR_WINDOWS_
#pragma comment(lib, "Irrlicht.lib")
#endif
struct SAppContext
{
IGUIListBox* listbox;
};
enum
{
GUI_ID_QUIT_BUTTON = 101,
GUI_ID_NEW_WINDOW_BUTTON,
GUI_ID_FILE_OPEN_BUTTON,
GUI_ID_TRANSPARENCY_SCROLL_BAR
};
The Irrlicht device. You can create it with createDevice() or createDeviceEx().
Main header file of the irrlicht, the only file needed to include.
Everything in the Irrlicht Engine can be found in this namespace.
signed int s32
32 bit signed variable.
Set the skin transparency by changing the alpha values of all skin-colors
{
{
skin->
setColor((EGUI_DEFAULT_COLOR)i, col);
}
}
A skin modifies the look of the GUI elements.
virtual void setColor(EGUI_DEFAULT_COLOR which, video::SColor newColor)=0
sets a default color
virtual video::SColor getColor(EGUI_DEFAULT_COLOR color) const =0
returns default color
Class representing a 32 bit ARGB color.
void setAlpha(u32 a)
Sets the alpha component of the Color.
The Event Receiver is not only capable of getting keyboard and mouse input events, but also events of the graphical user interface (gui). There are events for almost everything: Button click, Listbox selection change, events that say that a element was hovered and so on. To be able to react to some of these events, we create an event receiver. We only react to gui events, and if it's such an event, we get the id of the caller (the gui element which caused the event) and get the pointer to the gui environment.
{
public:
MyEventReceiver(SAppContext & context) : Context(context) { }
virtual bool OnEvent(
const SEvent& event)
{
{
s32 id =
event.GUIEvent.Caller->getID();
IGUIEnvironment* env = Context.device->getGUIEnvironment();
{
Interface of an object which can receive events.
gui::EGUI_EVENT_TYPE EventType
Type of GUI Event.
SEvents hold information about an event. See irr::IEventReceiver for details on event handling.
struct SGUIEvent GUIEvent
If a scrollbar changed its scroll position, and it is 'our' scrollbar (the one with id GUI_ID_TRANSPARENCY_SCROLL_BAR), then we change the transparency of all gui elements. This is a very easy task: There is a skin object, in which all color settings are stored. We simply go through all colors stored in the skin and change their alpha value.
case EGET_SCROLL_BAR_CHANGED:
if (id == GUI_ID_TRANSPARENCY_SCROLL_BAR)
{
setSkinTransparency(pos, env->getSkin());
}
break;
gui::IGUIElement * Caller
IGUIElement who called the event.
If a button was clicked, it could be one of 'our' three buttons. If it is the first, we shut down the engine. If it is the second, we create a little window with some text on it. We also add a string to the list box to log what happened. And if it is the third button, we create a file open dialog, and add also this as string to the list box. That's all for the event receiver.
case EGET_BUTTON_CLICKED:
switch(id)
{
case GUI_ID_QUIT_BUTTON:
Context.device->closeDevice();
return true;
case GUI_ID_NEW_WINDOW_BUTTON:
{
Context.listbox->addItem(L"Window created");
Context.counter += 30;
if (Context.counter > 200)
Context.counter = 0;
IGUIWindow* window = env->addWindow(
rect<s32>(100 + Context.counter, 100 + Context.counter, 300 + Context.counter, 200 + Context.counter),
false,
L"Test window");
env->addStaticText(L"Please close me",
rect<s32>(35,35,140,50),
true,
false,
window);
}
return true;
case GUI_ID_FILE_OPEN_BUTTON:
Context.listbox->addItem(L"File open");
env->addFileOpenDialog(L"Please choose a file.", true, 0, -1, true);
return true;
default:
return false;
}
break;
{
IGUIFileOpenDialog* dialog =
Context.listbox->addItem(dialog->getFileName());
}
break;
default:
break;
}
}
return false;
}
private:
SAppContext & Context;
};
@ EGET_FILE_SELECTED
A file has been selected in the file dialog.
Ok, now for the more interesting part. First, create the Irrlicht device. As in some examples before, we ask the user which driver he wants to use for this example:
int main()
{
if (driverType==video::EDT_COUNT)
return 1;
if (device == 0)
return 1;
Axis aligned bounding box in 3d dimensional space.
E_DRIVER_TYPE
An enum for all types of drivers the Irrlicht Engine supports.
The creation was successful, now we set the event receiver and store pointers to the driver and to the gui environment.
virtual void setWindowCaption(const wchar_t *text)=0
Sets the caption of the window.
virtual void setResizable(bool resize=false)=0
Sets if the window should be resizable in windowed mode.
virtual video::IVideoDriver * getVideoDriver()=0
Provides access to the video driver for drawing 3d and 2d geometry.
virtual gui::IGUIEnvironment * getGUIEnvironment()=0
Provides access to the 2d user interface environment.
Interface to driver which is able to perform 2d and 3d graphics functions.
To make the font a little bit nicer, we load an external font and set it as the new default font in the skin. To keep the standard font for tool tip text, we set it to the built-in font.
IGUISkin* skin = env->getSkin();
IGUIFont* font = env->
getFont(
"../../media/fonthaettenschweiler.bmp");
if (font)
skin->setFont(font);
skin->setFont(env->getBuiltInFont(), EGDF_TOOLTIP);
virtual IGUIFont * getFont(EGUI_DEFAULT_FONT which=EGDF_DEFAULT) const =0
returns the default font
We add three buttons. The first one closes the engine. The second creates a window and the third opens a file open dialog. The third parameter is the id of the button, with which we can easily identify the button in the event receiver.
env->addButton(rect<s32>(10,240,110,240 + 32), 0, GUI_ID_QUIT_BUTTON,
L"Quit", L"Exits Program");
env->addButton(rect<s32>(10,280,110,280 + 32), 0, GUI_ID_NEW_WINDOW_BUTTON,
L"New Window", L"Launches a new Window");
env->addButton(rect<s32>(10,320,110,320 + 32), 0, GUI_ID_FILE_OPEN_BUTTON,
L"File Open", L"Opens a file");
Now, we add a static text and a scrollbar, which modifies the transparency of all gui elements. We set the maximum value of the scrollbar to 255, because that's the maximal value for a color value. Then we create an other static text and a list box.
env->addStaticText(L"Transparent Control:", rect<s32>(150,20,350,40), true);
IGUIScrollBar* scrollbar = env->addScrollBar(true,
rect<s32>(150, 45, 350, 60), 0, GUI_ID_TRANSPARENCY_SCROLL_BAR);
scrollbar->setMax(255);
scrollbar->setPos(255);
setSkinTransparency( scrollbar->getPos(), env->getSkin());
scrollbar->setPos(env->getSkin()->getColor(EGDC_WINDOW).getAlpha());
env->addStaticText(L"Logging ListBox:", rect<s32>(50,110,250,130), true);
IGUIListBox * listbox = env->addListBox(rect<s32>(50, 140, 250, 210));
env->addEditBox(L"Editable Text", rect<s32>(350, 80, 550, 100));
SAppContext context;
context.device = device;
context.counter = 0;
context.listbox = listbox;
MyEventReceiver receiver(context);
virtual void setEventReceiver(IEventReceiver *receiver)=0
Sets a new user event receiver which will receive events from the engine.
And at last, we create a nice Irrlicht Engine logo in the top left corner.
env->addImage(driver->
getTexture(
"../../media/irrlichtlogo2.png"),
position2d<int>(10,10));
virtual ITexture * getTexture(const io::path &filename)=0
Get access to a named texture.
That's all, we only have to draw everything.
while(device->
run() && driver)
{
driver->
beginScene(
true,
true, SColor(0,200,200,200));
env->drawAll();
}
return 0;
}
bool drop() const
Drops the object. Decrements the reference counter by one.
virtual bool run()=0
Runs the device.
virtual bool isWindowActive() const =0
Returns if the window is active.
virtual bool beginScene(bool backBuffer=true, bool zBuffer=true, SColor color=SColor(255, 0, 0, 0), const SExposedVideoData &videoData=SExposedVideoData(), core::rect< s32 > *sourceRect=0)=0
Applications must call this method before performing any rendering.
virtual bool endScene()=0
Presents the rendered image to the screen.