Tutoriel Irrlicht 5

Interface Utilisateur

| Nikolaus Gebhart | Laurent Alexandre |

Traducteur

Neckara

Ce tutoriel est une traduction de l'anglais des tutoriels officiels d'Irrlicht.

Il montre comment utiliser l'interface utilisateur incluse dans le moteur Irrlicht. Il donnera un bref aperçu et montrera comment créer et utiliser des fenêtres, des boutons, des barres de défilement, des textes statiques et des listes déroulantes.

Commentez

- Titre : Tutoriel Irrlicht 5

- Auteurs : Nikolaus Gebhart, Laurent Alexandre

- Traducteur : Neckara

- Parution : 30 avril 2013

- Mise à jour : 30 avril 2013

- Public visé :

- Licence : Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright ® 2013 Neckara. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.

Sommaire

- I. Gestion des événements

- I-A. Événement généré par la barre de défilement

- I-B. Événement généré par les boutons

- II. Mise en place des éléments de l'interface utilisateur

- III. Conclusion

- IV. Remerciements

I - Gestion des événements

Comme toujours, nous incluons les fichiers d'en-têtes, et nous utilisons l'espace de nommage d'Irrlicht. Nous stockons aussi un pointeur sur le moteur d'Irrlicht, un compteur pour changer la position d'une fenêtre à sa création, et un pointeur sur une liste déroulante.

#include <irrlicht.h>
#include "driverChoice.h"

using namespace irr;

using namespace core;
using namespace scene;
using namespace video;
using namespace io;
using namespace gui;

#ifdef _IRR_WINDOWS_
#pragma comment(lib, "Irrlicht.lib")
#endif

// Déclare une structure pour stocker le contexte du receveur d'événement
// dont il a besoin dans sa méthode OnEvent().
struct SAppContext
{
IrrlichtDevice *device;
s32             counter;
IGUIListBox*    listbox;
};

// Défini quelques valeurs que nous utiliserons pour identifier les différents contrôles de l'interface utilisateur.
enum
{
GUI_ID_QUIT_BUTTON = 101,
GUI_ID_NEW_WINDOW_BUTTON,
GUI_ID_FILE_OPEN_BUTTON,
GUI_ID_TRANSPARENCY_SCROLL_BAR
};

Le receveur d'événement n'est pas seulement capable d'obtenir les événements d'entrée du clavier et de la souris, mais il peut aussi obtenir les événements de l'interface utilisateur graphique. Il y a des événements pour presque tout : les clics de boutons, le changement de sélection dans une liste déroulante, des événements qui disent qu'un élément a été survolé et bien plus. Pour être capable de réagir à ces événements, nous créons un receveur d'événement. Nous ne réagirons qu'aux événements de l'interface graphique, et si c'est le cas, nous obtenons l'identifiant de l'appelant (l'élément de l'interface à l'origine de l'événement) et nous obtenons un pointeur sur l'environnement de l'interface.

class MyEventReceiver : public IEventReceiver
{
public:
MyEventReceiver(SAppContext & context) : Context(context) { }

virtual bool OnEvent(const SEvent& event)
{
if (event.EventType == EET_GUI_EVENT)
{
s32 id = event.GUIEvent.Caller->getID();
IGUIEnvironment* env = Context.device->getGUIEnvironment();

switch(event.GUIEvent.EventType)
{

I-A - Événement généré par la barre de défilement

Si une barre de défilement voit sa position changée, et si c'est la nôtre (celle avec l'identifiant GUI_ID_TRANSPARENCY_SCROLL_BAR), alors nous changeons la transparence de tous les éléments de l'interface. Ceci est très facile : il y a un objet « skin », dans lequel tous les paramètres des couleurs sont stockés. Nous parcourons simplement toutes les couleurs stockées dans le « skin » et nous changeons leur valeur alpha.

case EGET_SCROLL_BAR_CHANGED:
if (id == GUI_ID_TRANSPARENCY_SCROLL_BAR)
{
s32 pos = ((IGUIScrollBar*)event.GUIEvent.Caller)->getPos();

for (u32 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;

I-B - Événement généré par les boutons

Si un bouton a été cliqué, il pourrait bien être l'un de nos trois boutons. Si c'est le premier, nous arrêtons le moteur. Si c'est le second, nous créons une petite fenêtre avec du texte dedans. Nous ajoutons aussi une chaîne de caractères à la liste déroulante pour inscrire ce qu'il se passe. Et si c'est le troisième bouton, nous créons une pop-up d'ouverture de fichier et nous ajoutons le nom du fichier sélectionné comme une nouvelle entrée dans notre liste déroulante. C'est tout pour le receveur d'événement.

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, // modal?
L"Test window");

env->addStaticText(L"Please close me",
rect<s32>(35,35,140,50),
true, // bordure ?
false, // retours à la ligne ?
window);
}
return true;

case GUI_ID_FILE_OPEN_BUTTON:
Context.listbox->addItem(L"File open");
// Il y a quelques options pour l'ouverture de fichier.
// Nous mettons le titre, indiquons qu'elle sera une fenêtre modale et nous assurons
// que le dossier de travail est restauré après que la fenêtre se soit fermée.
env->addFileOpenDialog(L"Please choose a file.", true, 0, -1, true);
return true;

default:
return false;
}
break;

case EGET_FILE_SELECTED:
{
// Montre le nom du fichier sélectionné dans la fenêtre d'ouverture de fichier.
IGUIFileOpenDialog* dialog =
(IGUIFileOpenDialog*)event.GUIEvent.Caller;
Context.listbox->addItem(dialog->getFileName());
}
break;

default:
break;
}
}

return false;
}

private:
SAppContext & Context;
};

II - Mise en place des éléments de l'interface utilisateur

Ok, maintenant la partie la plus intéressante. Premièrement, nous créons le moteur Irrlicht. Comme dans certains exemples précédents, nous demandons à l'utilisateur quel pilote il veut utiliser pour cet exemple :

int main()
{
// demande à l'utilisateur un pilote à utiliser
video::E_DRIVER_TYPE driverType=driverChoiceConsole();
if (driverType==video::EDT_COUNT)
return 1;

// crée un moteur et quitte si la création a échouée

IrrlichtDevice * device = createDevice(driverType, core::dimension2d<u32>(640, 480));

if (device == 0)
return 1; // on ne peut pas créer le pilote sélectionné

La création a réussie, maintenant nous installons le receveur d'événement et nous stockons le pilote dans l'environnement de l'interface utilisateur.

device->setWindowCaption(L"Irrlicht Engine - User Interface Demo");
device->setResizable(true);

video::IVideoDriver* driver = device->getVideoDriver();
IGUIEnvironment* env = device->getGUIEnvironment();

Pour rendre la police plus jolie, nous chargeons une police externe et nous la définissons comme nouvelle police par défaut du « skin ». Pour garder la police standard pour les info-bulles, nous la définissons comme police intégrée.

IGUISkin* skin = env->getSkin();
IGUIFont* font = env->getFont("../../media/fonthaettenschweiler.bmp");
if (font)
skin->setFont(font);

skin->setFont(env->getBuiltInFont(), EGDF_TOOLTIP);

Nous ajoutons trois boutons. Le premier ferme le moteur. Le second crée une fenêtre et le troisième ouvre une pop-up d'ouverture de fichier. Le troisième paramètre est l'identifiant du bouton avec lequel nous pouvons facilement identifier le bouton dans le receveur d'événement.

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");

Maintenant nous ajoutons un texte statique et une barre de défilement, qui modifie la transparence de tous les éléments de l'interface utilisateur. Nous mettons la valeur maximale de la barre de défilement à 255 parce que c'est la valeur maximale pour une valeur de couleur. Après nous créons un autre texte statique et la liste déroulante.

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);

// met la position de la barre de défilement à la valeur alpha d'un élément choisi arbitrairement
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));

// Stocke les données appropriées dans la structure de contexte.
SAppContext context;
context.device = device;
context.counter = 0;
context.listbox = listbox;

// Enfin, crée le receveur d'événement, on lui donne la structure de contexte.
MyEventReceiver receiver(context);

// Et nous disons au moteur d'utiliser notre receveur d'événement personnel.
device->setEventReceiver(&receiver);

Et finalement, nous créons le joli logo du moteur Irrlicht.

env->addImage(driver->getTexture("../../media/irrlichtlogo2.png"),
position2d<int>(10,10));

C'est tout, il nous reste plus qu'à tout dessiner.

while(device->run() && driver)
if (device->isWindowActive())
{
driver->beginScene(true, true, SColor(0,200,200,200));

env->drawAll();

driver->endScene();
}

device->drop();

return 0;
}

III - Conclusion

Vous pouvez désormais construire votre propre interface utilisateur avec Irrlicht.

Dans le prochain tutoriel : Graphisme 2D, nous verrons comment afficher des images 2D avec le moteur Irrlicht, il vous permettra par exemple de dessiner une interface personnalisée.

IV - Remerciements

Merci à Nikolaus Gebhardt de nous permettre de traduire ce tutoriel.

Merci à LittleWhite pour sa relecture technique ainsi qu'à f-leb pour sa relecture orthographique.