Tutorial 5: User Interface (Benutzeroberfläche)(Übersetzt von Ba'el, orig. eng. irrlicht.sourceforge.net)
Dieses Tutorial zeigt wie man sich ein User Interface der Irrlicht Engine bastelt. Es gibt eine kurze übersicht und zeigt wie man Fenster, Buttons, Bildlaufleisten, Statische Texte und Auflistungsboxen erstellt und nutzt.
Das Programm wird am Ende so aussehen:

Los gehts!
Wie immer includen wir die header files (conio and curses for getting user input from the console), und nutzen die irrlicht namespaces. Wir speichen auch einen Pointer auf die Irrlicht device, eine Zählvariable um die Position zum erstellen eines Fensters, und ein Pointer auf eine Auflistungsbox.
Code:
#include <irrlicht.h>
#include <iostream>
using namespace irr;
using namespace core;
using namespace scene;
using namespace video;
using namespace io;
using namespace gui;
#pragma comment(lib, "Irrlicht.lib")
IrrlichtDevice *device = 0;
s32 cnt = 0;
IGUIListBox* listbox = 0;
Die Klasse zum Erkennen von Ereignissen kann nicht nur die von Maus und Tastatur gesendeten Ereignisse Empfangen und darauf reagieren, sondern auch solche von der graphischen Benutzteroberfläche (gui). Das sind die Ereignisse von nahezu allem: drücken eines Button, durch Selektierung in der Auflistungsbox wechseln und so weiter. Um das Reagieren auf solche Ereignisse möglich zu machen müssen wir einen "Ereignissempfänger" erstellen. Wir reagieren hier nur auf GUI-Ereignisse, und wenn ein solches Ereigniss eintrifft geben wir die ID des Aufrufers (das GUI-Element welches das Ereignis erzeugt) und den Pointer an die GUI-Umgebung.
Code:
class MyEventReceiver : public IEventReceiver
{
public:
virtual bool OnEvent(SEvent event)
{
if (event.EventType == EET_GUI_EVENT)
{
s32 id = event.GUIEvent.Caller->getID();
IGUIEnvironment* env = device->getGUIEnvironment();
switch(event.GUIEvent.EventType)
{
Wenn die Bildlaufleiste ihre Position ändert, und es ist 'unserer' Bildlaufleiste (nämlich die mit der ID 104), dann wird die Transparenz aller GUI-Elemente verändert. Das ist eine ganz einfache Aufgabe: Da ist nämlich ein Oberflächenobjekt, in dem alle Farbeinstellungen gespeichert sind. Wir gehen einfach durch alle Farben welche in der Oberfläche gespeichert sind und ändern ihre Alphawerte.
Code:
case EGET_SCROLL_BAR_CHANGED:
if (id == 104)
{
s32 pos = ((IGUIScrollBar*)event.GUIEvent.Caller)->getPos();
for (s32 i=0; i<EGDC_COUNT ; ++i)
{
SColor col = env->getSkin()->getColor((EGUI_DEFAULT_COLOR)i);
col.setAlpha(pos);
env->getSkin()->setColor((EGUI_DEFAULT_COLOR)i, col);
}
}
break;
Wenn ein Button geklickt wird könnte es einer 'unserer' drei Buttons sein. Wenn es der Erste ist beenden wir die Engine.
Wenn es der Zweite ist erstellen wir ein kleines Fenster, mit irgend einem Text drin. Und wir fügen einen String in die Auflistungsbox um zu vermerken was wir gemacht haben. Und wenn es der Dritte Button ist erstellen wir einen "Datei öffnen"-Dialog und fügen wiederum einen String in die Auflistungsbox ein.
Das ist der Rest für den "event receiverâ€.
Code:
case EGET_BUTTON_CLICKED:
if (id == 101)
{
device->closeDevice();
return true;
}
if (id == 102)
{
listbox->addItem(L"Window created");
cnt += 30;
if (cnt > 200)
cnt = 0;
IGUIWindow* window = env->addWindow(
rect<s32>(100 + cnt, 100 + cnt, 300 + cnt, 200 + cnt),
false, // modal?
L"Test window");
env->addStaticText(L"Please close me",
rect<s32>(35,35,140,50),
true, // border?,
false, // wordwrap?
window);
return true;
}
if (id == 103)
{
listbox->addItem(L"File open");
env->addFileOpenDialog(L"Please choose a file.");
return true;
}
break;
}
}
return false;
}
};
Ok, kommen wir nun zu dem interessanteren Teil. Als Erstes erstellen wir das Irrlicht device. Wie in den anderen Tutorials zuvor fragen wir den Benutzer welchen Treiber er benutzen will:
Code:
int main()
{
// ask user for driver
video::E_DRIVER_TYPE driverType;
printf("Please select the driver you want for this example:\n"\
" (a) Direct3D 9.0c\n (b) Direct3D 8.1\n (c) OpenGL 1.5\n"\
" (d) Software Renderer\n (e) Apfelbaum Software Renderer\n"\
" (f) NullDevice\n (otherKey) exit\n\n");
char i;
std::cin >> i;
switch(i)
{
case 'a': driverType = video::EDT_DIRECT3D9;break;
case 'b': driverType = video::EDT_DIRECT3D8;break;
case 'c': driverType = video::EDT_OPENGL; break;
case 'd': driverType = video::EDT_SOFTWARE; break;
case 'e': driverType = video::EDT_SOFTWARE2;break;
case 'f': driverType = video::EDT_NULL; break;
default: return 1;
}
// create device and exit if creation failed
device = createDevice(driverType, core::dimension2d<s32>(640, 480));
if (device == 0)
return 1;
Das bekannte Menü wäre fertig, nun kommen wir zum "event receiver†und speichern Pointer auf die Treiber und die GUI-Umgebung.
Code:
MyEventReceiver receiver;
device->setEventReceiver(&receiver);
device->setWindowCaption(L"Irrlicht Engine - User Inferface Demo");
video::IVideoDriver* driver = device->getVideoDriver();
IGUIEnvironment* env = device->getGUIEnvironment();
Nun fügen wir noch die drei Buttons hinzu. Der dritte Parameter ist die ID des Button, mit der wir ganz einfach die Butten in "event receiver" identifizieren können.
Code:
env->addButton(rect<s32>(10,210,100,240), 0, 101, L"Quit");
env->addButton(rect<s32>(10,250,100,290), 0, 102, L"New Window");
env->addButton(rect<s32>(10,300,100,340), 0, 103, L"File Open");
Jetzt kommen der statische Text und eine Bildlaufleiste hinzu, welche die Transparenz der gesamten GUI-Elemente ändert. Wir setzen den maximalen Wert der Scrollbar auf 255, da das auch der maximale Wert bei der Farbe ist.
Dann erstellen wir noch einen anderen statischen Text und eine Auflistungsbox.
Code:
env->addStaticText(L"Transparent Control:", rect<s32>(150,20,350,40), true);
IGUIScrollBar* scrollbar = env->addScrollBar(true,
rect<s32>(150, 45, 350, 60), 0, 104);
scrollbar->setMax(255);
env->addStaticText(L"Logging ListBox:", rect<s32>(50,80,250,100), true);
listbox = env->addListBox(rect<s32>(50, 110, 250, 180));
Um die Schriftart ein bisschen schöner zu machen laden wir eine externe Schriftart und setzen diese in die Oberfläche. Und zum schluss erstellen wir noch ein schönes Irrlicht Engine Logo in der oberen linken Ecke.
Code:
IGUISkin* skin = env->getSkin();
IGUIFont* font = env->getFont("../../media/fonthaettenschweiler.bmp");
if (font)
skin->setFont(font);
IGUIImage* img = env->addImage(
driver->getTexture("../../media/irrlichtlogoalpha.tga"),
position2d<int>(10,10));
Das war's, wir müssen nur noch alles zeichnen.
Code:
while(device->run() && driver)
if (device->isWindowActive())
{
driver->beginScene(true, true, SColor(0,122,65,171));
env->drawAll();
driver->endScene();
}
device->drop();
return 0;
}