]> git.lizzy.rs Git - irrlicht.git/blob - examples/05.UserInterface/main.cpp
Merging r5975 through r6036 from trunk to ogl-es branch.
[irrlicht.git] / examples / 05.UserInterface / main.cpp
1 /** Example 005 User Interface\r
2 \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
7 \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
12 */\r
13 #include <irrlicht.h>\r
14 #include "driverChoice.h"\r
15 #include "exampleHelper.h"\r
16 \r
17 using namespace irr;\r
18 \r
19 using namespace core;\r
20 using namespace scene;\r
21 using namespace video;\r
22 using namespace io;\r
23 using namespace gui;\r
24 \r
25 #ifdef _MSC_VER\r
26 #pragma comment(lib, "Irrlicht.lib")\r
27 #endif\r
28 \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
31 struct SAppContext\r
32 {\r
33         IrrlichtDevice *device;\r
34         s32                             counter;\r
35         IGUIListBox*    listbox;\r
36 };\r
37 \r
38 // Define some values that we'll use to identify individual GUI controls.\r
39 enum\r
40 {\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
45 };\r
46 \r
47 /*\r
48         Set the skin transparency by changing the alpha values of all skin-colors\r
49 */\r
50 void setSkinTransparency(s32 alpha, irr::gui::IGUISkin * skin)\r
51 {\r
52         for (s32 i=0; i<irr::gui::EGDC_COUNT ; ++i)\r
53         {\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
57         }\r
58 }\r
59 \r
60 /*\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
66 an event receiver.\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
70 */\r
71 class MyEventReceiver : public IEventReceiver\r
72 {\r
73 public:\r
74         MyEventReceiver(SAppContext & context) : Context(context) { }\r
75 \r
76         virtual bool OnEvent(const SEvent& event)\r
77         {\r
78                 if (event.EventType == EET_GUI_EVENT)\r
79                 {\r
80                         s32 id = event.GUIEvent.Caller->getID();\r
81                         IGUIEnvironment* env = Context.device->getGUIEnvironment();\r
82 \r
83                         switch(event.GUIEvent.EventType)\r
84                         {\r
85 \r
86                         /*\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
93                         */\r
94                         case EGET_SCROLL_BAR_CHANGED:\r
95                                 if (id == GUI_ID_TRANSPARENCY_SCROLL_BAR)\r
96                                 {\r
97                                         s32 pos = ((IGUIScrollBar*)event.GUIEvent.Caller)->getPos();\r
98                                         setSkinTransparency(pos, env->getSkin());\r
99                                 }\r
100                                 break;\r
101 \r
102                         /*\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
110                         */\r
111                         case EGET_BUTTON_CLICKED:\r
112                                 switch(id)\r
113                                 {\r
114                                 case GUI_ID_QUIT_BUTTON:\r
115                                         Context.device->closeDevice();\r
116                                         return true;\r
117 \r
118                                 case GUI_ID_NEW_WINDOW_BUTTON:\r
119                                         {\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
124 \r
125                                         IGUIWindow* window = env->addWindow(\r
126                                                 rect<s32>(100 + Context.counter, 100 + Context.counter, 300 + Context.counter, 200 + Context.counter),\r
127                                                 false, // modal?\r
128                                                 L"Test window");\r
129 \r
130                                         env->addStaticText(L"Please close me",\r
131                                                 rect<s32>(35,35,140,50),\r
132                                                 true, // border?\r
133                                                 false, // wordwrap?\r
134                                                 window);\r
135                                         }\r
136                                         return true;\r
137 \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
143                                         // is finished.\r
144                                         env->addFileOpenDialog(L"Please choose a file.", true, 0, -1, true);\r
145                                         return true;\r
146 \r
147                                 default:\r
148                                         return false;\r
149                                 }\r
150                                 break;\r
151 \r
152                         case EGET_FILE_SELECTED:\r
153                                 {\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
158                                 }\r
159                                 break;\r
160 \r
161                         default:\r
162                                 break;\r
163                         }\r
164                 }\r
165 \r
166                 return false;\r
167         }\r
168 \r
169 private:\r
170         SAppContext & Context;\r
171 };\r
172 \r
173 \r
174 /*\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
177 example.\r
178 */\r
179 int main()\r
180 {\r
181         // ask user for driver\r
182         video::E_DRIVER_TYPE driverType=driverChoiceConsole();\r
183         if (driverType==video::EDT_COUNT)\r
184                 return 1;\r
185 \r
186         // create device and exit if creation failed\r
187         IrrlichtDevice * device = createDevice(driverType, core::dimension2d<u32>(640, 480));\r
188 \r
189         if (device == 0)\r
190                 return 1; // could not create selected driver.\r
191 \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
194 \r
195         device->setWindowCaption(L"Irrlicht Engine - User Interface Demo");\r
196         device->setResizable(true);\r
197 \r
198         video::IVideoDriver* driver = device->getVideoDriver();\r
199         IGUIEnvironment* env = device->getGUIEnvironment();\r
200 \r
201         const io::path mediaPath = getExampleMediaPath();\r
202 \r
203         /*\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
207         the built-in font.\r
208         */\r
209 \r
210         IGUISkin* skin = env->getSkin();\r
211         IGUIFont* font = env->getFont(mediaPath + "fonthaettenschweiler.bmp");\r
212         if (font)\r
213                 skin->setFont(font);\r
214 \r
215         skin->setFont(env->getBuiltInFont(), EGDF_TOOLTIP);\r
216 \r
217         /*\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
222         */\r
223 \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
230 \r
231         /*\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
235         a color value.\r
236         Then we create an other static text and a list box.\r
237         */\r
238 \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
245 \r
246         // set scrollbar position to alpha value of an arbitrary element\r
247         scrollbar->setPos(env->getSkin()->getColor(EGDC_WINDOW).getAlpha());\r
248 \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
252 \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
258 \r
259         // Then create the event receiver, giving it that context structure.\r
260         MyEventReceiver receiver(context);\r
261 \r
262         // And tell the device to use our custom event receiver.\r
263         device->setEventReceiver(&receiver);\r
264 \r
265 \r
266         /*\r
267         And at last, we create a nice Irrlicht Engine logo in the top left corner.\r
268         */\r
269         env->addImage(driver->getTexture(mediaPath + "irrlichtlogo2.png"),\r
270                         position2d<int>(10,10));\r
271 \r
272 \r
273         /*\r
274         That's all, we only have to draw everything.\r
275         */\r
276 \r
277         while(device->run() && driver)\r
278         if (device->isWindowActive())\r
279         {\r
280                 driver->beginScene(video::ECBF_COLOR | video::ECBF_DEPTH, SColor(0,200,200,200));\r
281 \r
282                 env->drawAll();\r
283 \r
284                 driver->endScene();\r
285         }\r
286 \r
287         device->drop();\r
288 \r
289         return 0;\r
290 }\r
291 \r
292 /*\r
293 **/\r