1 /** Example 005 User Interface
\r
3 This tutorial shows how to use the built in User Interface of
\r
4 the Irrlicht Engine. It will give a brief overview and show
\r
5 how to create and use windows, buttons, scroll bars, static
\r
6 texts, and list boxes.
\r
8 As always, we include the header files, and use the irrlicht
\r
9 namespaces. We also store a pointer to the Irrlicht device,
\r
10 a counter variable for changing the creation position of a window,
\r
11 and a pointer to a listbox.
\r
13 #include <irrlicht.h>
\r
14 #include "driverChoice.h"
\r
15 #include "exampleHelper.h"
\r
17 using namespace irr;
\r
19 using namespace core;
\r
20 using namespace scene;
\r
21 using namespace video;
\r
23 using namespace gui;
\r
26 #pragma comment(lib, "Irrlicht.lib")
\r
29 // Declare a structure to hold some context for the event receiver so that it
\r
30 // has it available inside its OnEvent() method.
\r
33 IrrlichtDevice *device;
\r
35 IGUIListBox* listbox;
\r
38 // Define some values that we'll use to identify individual GUI controls.
\r
41 GUI_ID_QUIT_BUTTON = 101,
\r
42 GUI_ID_NEW_WINDOW_BUTTON,
\r
43 GUI_ID_FILE_OPEN_BUTTON,
\r
44 GUI_ID_TRANSPARENCY_SCROLL_BAR
\r
48 Set the skin transparency by changing the alpha values of all skin-colors
\r
50 void setSkinTransparency(s32 alpha, irr::gui::IGUISkin * skin)
\r
52 for (s32 i=0; i<irr::gui::EGDC_COUNT ; ++i)
\r
54 video::SColor col = skin->getColor((EGUI_DEFAULT_COLOR)i);
\r
55 col.setAlpha(alpha);
\r
56 skin->setColor((EGUI_DEFAULT_COLOR)i, col);
\r
61 The Event Receiver is not only capable of getting keyboard and
\r
62 mouse input events, but also events of the graphical user interface
\r
63 (gui). There are events for almost everything: button click,
\r
64 listbox selection change, events that say that a element was hovered
\r
65 and so on. To be able to react to some of these events, we create
\r
67 We only react to gui events, and if it's such an event, we get the
\r
68 id of the caller (the gui element which caused the event) and get
\r
69 the pointer to the gui environment.
\r
71 class MyEventReceiver : public IEventReceiver
\r
74 MyEventReceiver(SAppContext & context) : Context(context) { }
\r
76 virtual bool OnEvent(const SEvent& event)
\r
78 if (event.EventType == EET_GUI_EVENT)
\r
80 s32 id = event.GUIEvent.Caller->getID();
\r
81 IGUIEnvironment* env = Context.device->getGUIEnvironment();
\r
83 switch(event.GUIEvent.EventType)
\r
87 If a scrollbar changed its scroll position, and it is
\r
88 'our' scrollbar (the one with id GUI_ID_TRANSPARENCY_SCROLL_BAR),
\r
89 then we change the transparency of all gui elements. This is an
\r
90 easy task: There is a skin object, in which all color
\r
91 settings are stored. We simply go through all colors
\r
92 stored in the skin and change their alpha value.
\r
94 case EGET_SCROLL_BAR_CHANGED:
\r
95 if (id == GUI_ID_TRANSPARENCY_SCROLL_BAR)
\r
97 s32 pos = ((IGUIScrollBar*)event.GUIEvent.Caller)->getPos();
\r
98 setSkinTransparency(pos, env->getSkin());
\r
103 If a button was clicked, it could be one of 'our'
\r
104 three buttons. If it is the first, we shut down the engine.
\r
105 If it is the second, we create a little window with some
\r
106 text on it. We also add a string to the list box to log
\r
107 what happened. And if it is the third button, we create
\r
108 a file open dialog, and add also this as string to the list box.
\r
109 That's all for the event receiver.
\r
111 case EGET_BUTTON_CLICKED:
\r
114 case GUI_ID_QUIT_BUTTON:
\r
115 Context.device->closeDevice();
\r
118 case GUI_ID_NEW_WINDOW_BUTTON:
\r
120 Context.listbox->addItem(L"Window created");
\r
121 Context.counter += 30;
\r
122 if (Context.counter > 200)
\r
123 Context.counter = 0;
\r
125 IGUIWindow* window = env->addWindow(
\r
126 rect<s32>(100 + Context.counter, 100 + Context.counter, 300 + Context.counter, 200 + Context.counter),
\r
130 env->addStaticText(L"Please close me",
\r
131 rect<s32>(35,35,140,50),
\r
133 false, // wordwrap?
\r
138 case GUI_ID_FILE_OPEN_BUTTON:
\r
139 Context.listbox->addItem(L"File open");
\r
140 // There are some options for the file open dialog
\r
141 // We set the title, make it a modal window, and make sure
\r
142 // that the working directory is restored after the dialog
\r
144 env->addFileOpenDialog(L"Please choose a file.", true, 0, -1, true);
\r
152 case EGET_FILE_SELECTED:
\r
154 // show the model filename, selected in the file dialog
\r
155 IGUIFileOpenDialog* dialog =
\r
156 (IGUIFileOpenDialog*)event.GUIEvent.Caller;
\r
157 Context.listbox->addItem(dialog->getFileName());
\r
170 SAppContext & Context;
\r
175 OK, now for the more interesting part. First, create the Irrlicht device. As in
\r
176 some examples before, we ask the user which driver he wants to use for this
\r
181 // ask user for driver
\r
182 video::E_DRIVER_TYPE driverType=driverChoiceConsole();
\r
183 if (driverType==video::EDT_COUNT)
\r
186 // create device and exit if creation failed
\r
187 IrrlichtDevice * device = createDevice(driverType, core::dimension2d<u32>(640, 480));
\r
190 return 1; // could not create selected driver.
\r
192 /* The creation was successful, now we set the event receiver and
\r
193 store pointers to the driver and to the gui environment. */
\r
195 device->setWindowCaption(L"Irrlicht Engine - User Interface Demo");
\r
196 device->setResizable(true);
\r
198 video::IVideoDriver* driver = device->getVideoDriver();
\r
199 IGUIEnvironment* env = device->getGUIEnvironment();
\r
201 const io::path mediaPath = getExampleMediaPath();
\r
204 To make the font a little bit nicer, we load an external font
\r
205 and set it as the new default font in the skin.
\r
206 To keep the standard font for tool tip text, we set it to
\r
210 IGUISkin* skin = env->getSkin();
\r
211 IGUIFont* font = env->getFont(mediaPath + "fonthaettenschweiler.bmp");
\r
213 skin->setFont(font);
\r
215 skin->setFont(env->getBuiltInFont(), EGDF_TOOLTIP);
\r
218 We add three buttons. The first one closes the engine. The second
\r
219 creates a window and the third opens a file open dialog. The third
\r
220 parameter is the id of the button, with which we can easily identify
\r
221 the button in the event receiver.
\r
224 env->addButton(rect<s32>(10,240,110,240 + 32), 0, GUI_ID_QUIT_BUTTON,
\r
225 L"Quit", L"Exits Program");
\r
226 env->addButton(rect<s32>(10,280,110,280 + 32), 0, GUI_ID_NEW_WINDOW_BUTTON,
\r
227 L"New Window", L"Launches a new Window");
\r
228 env->addButton(rect<s32>(10,320,110,320 + 32), 0, GUI_ID_FILE_OPEN_BUTTON,
\r
229 L"File Open", L"Opens a file");
\r
232 Now, we add a static text and a scrollbar, which modifies the
\r
233 transparency of all gui elements. We set the maximum value of
\r
234 the scrollbar to 255, because that's the maximal value for
\r
236 Then we create an other static text and a list box.
\r
239 env->addStaticText(L"Transparent Control:", rect<s32>(150,20,350,40), true);
\r
240 IGUIScrollBar* scrollbar = env->addScrollBar(true,
\r
241 rect<s32>(150, 45, 350, 60), 0, GUI_ID_TRANSPARENCY_SCROLL_BAR);
\r
242 scrollbar->setMax(255);
\r
243 scrollbar->setPos(255);
\r
244 setSkinTransparency( scrollbar->getPos(), env->getSkin());
\r
246 // set scrollbar position to alpha value of an arbitrary element
\r
247 scrollbar->setPos(env->getSkin()->getColor(EGDC_WINDOW).getAlpha());
\r
249 env->addStaticText(L"Logging ListBox:", rect<s32>(50,110,250,130), true);
\r
250 IGUIListBox * listbox = env->addListBox(rect<s32>(50, 140, 250, 210));
\r
251 env->addEditBox(L"Editable Text", rect<s32>(350, 80, 550, 100));
\r
253 // Store the appropriate data in a context structure.
\r
254 SAppContext context;
\r
255 context.device = device;
\r
256 context.counter = 0;
\r
257 context.listbox = listbox;
\r
259 // Then create the event receiver, giving it that context structure.
\r
260 MyEventReceiver receiver(context);
\r
262 // And tell the device to use our custom event receiver.
\r
263 device->setEventReceiver(&receiver);
\r
267 And at last, we create a nice Irrlicht Engine logo in the top left corner.
\r
269 env->addImage(driver->getTexture(mediaPath + "irrlichtlogo2.png"),
\r
270 position2d<int>(10,10));
\r
274 That's all, we only have to draw everything.
\r
277 while(device->run() && driver)
\r
278 if (device->isWindowActive())
\r
280 driver->beginScene(video::ECBF_COLOR | video::ECBF_DEPTH, SColor(0,200,200,200));
\r
284 driver->endScene();
\r