Tutorial 5 - User Interface - Chip - 10-08-2015
Tutorial 5: User Interface
Questo tutorial spiega come utilizzare la User Interface (UI) integrata in Irrlicht Engine. Verrà fornita una breve panoramica su come si creano finestre, pulsanti, scrollbars, etichette di testo e listbox. Come sempre iniziamo mostrando l'header dove si utilizza il namespace irr e diamo indicazioni al linker di inserire la libreria irrlicht.lib. Creiamo anche una variabile puntatore al device Irrlicht, una variabile per gestire la posizione della finestra e un puntatore ad una listbox.
Codice PHP: #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
// Declare a structure to hold some context for the event receiver so that it // has it available inside its OnEvent() method. struct SAppContext { IrrlichtDevice *device; s32 counter; IGUIListBox* listbox; };
// Define some values that we'll use to identify individual GUI controls. enum { GUI_ID_QUIT_BUTTON = 101, GUI_ID_NEW_WINDOW_BUTTON, GUI_ID_FILE_OPEN_BUTTON, GUI_ID_TRANSPARENCY_SCROLL_BAR };
Variamo la trasparenza dello skin della nostra GUI agendo sul valore alpha della proprietà skin-colors.
Codice PHP: void setSkinTransparency(s32 alpha, irr::gui::IGUISkin * skin) { for (s32 i=0; i<irr::gui::EGDC_COUNT ; ++i) { video::SColor col = skin->getColor((EGUI_DEFAULT_COLOR)i); col.setAlpha(alpha); skin->setColor((EGUI_DEFAULT_COLOR)i, col); } }
L'Event Receiver non è solo in grado di catturare gli eventi dalla tastiera o dal mouse, può anche catturare gli eventi che provengono dalla GUI. Ogni componente ha i suoi eventi: un click sul pulsante, la selezione di un range per la Listbox, tutti eventi che ci dicono quando un elemento ha interagito con i nostri input. Per gestire la reazione a questi eventi creiamo un event receiver. Reagiremo solo ad eventi della GUI e quando ciò accadrà andremo a prenderci l'id del chiamante (cioè identifichiamo chi della componente GUI ha sollevato l'evento) e con questo otterremo il puntatore a quell'elemento grafico.
Codice PHP: 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) {
Quando la scrollbar cambia la sua posizione e capiamo che si tratta della “nostra” (quella con l'id GUI_ID_TRANSPARENCY_SCROLL_BAR) allora andremo a cambiare la trasparenza di tutti gli elementi della GUI. La cosa è facile perché c'è l'oggetto skin che contiene tutti i settaggi dei colori. Basterà scorrerci tutti questi valori e cambiare di conseguenza il valore alpha.
Codice PHP: case EGET_SCROLL_BAR_CHANGED: if (id == GUI_ID_TRANSPARENCY_SCROLL_BAR) { s32 pos = ((IGUIScrollBar*)event.GUIEvent.Caller)->getPos(); setSkinTransparency(pos, env->getSkin()); } break;
Quando un pulsante è premuto ed è uno dei nostri. Se è il primo chiudiamo l'engine. Se il secondo andiamo a creare un'altra finestra con del testo dentro “Test windows”. Inseriamo anche nella listbox che fa da log quello che accade. Se è il terzo pulsante apriamo una finestra di dialogo di tipo “Apri file” e anche in questo caso aggiungiamo al log sulla listbox. Questo è tutto per levent receiver.
Codice PHP: 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, // border? false, // wordwrap? window); } return true;
case GUI_ID_FILE_OPEN_BUTTON: Context.listbox->addItem(L"File open"); // There are some options for the file open dialog // We set the title, make it a modal window, and make sure // that the working directory is restored after the dialog // is finished. env->addFileOpenDialog(L"Please choose a file.", true, 0, -1, true); return true; default: return false; } break;
case EGET_FILE_SELECTED: { // show the model filename, selected in the file dialog IGUIFileOpenDialog* dialog = (IGUIFileOpenDialog*)event.GUIEvent.Caller; Context.listbox->addItem(dialog->getFileName()); } break; default: break; } } return false; } private: SAppContext & Context; };
Ok ora la parte più interessante. Primo creiamo il device Irrlicht. Come in un esempio precedente chiediamo all'utente che genere di device vuole utilizzare (risoluzione, ecc..):
Codice PHP: int main() { // ask user for driver video::E_DRIVER_TYPE driverType=driverChoiceConsole(); if (driverType==video::EDT_COUNT) return 1;
// create device and exit if creation failed
IrrlichtDevice * device = createDevice(driverType, core::dimension2d<u32>(640, 480));
if (device == 0) return 1; // could not create selected driver.
Se il device è stato creato correttamente settiamo il nostro event receiver e prendiamoci il puntatore al nostro driver e quello del nostro nuovi ambiente GUI.
Codice PHP: device->setWindowCaption(L"Irrlicht Engine - User Interface Demo"); device->setResizable(true); video::IVideoDriver* driver = device->getVideoDriver(); IGUIEnvironment* env = device->getGUIEnvironment();
Per rendere il font un po' più carino, carichiamone uno esterno e lo settiamo come default per la skin della nostra GUI. Per mantenere invece il font standard sui tool tip, lo andiamo a reimpostare tramite la proprietà getBuiltInFont().
Codice PHP: IGUISkin* skin = env->getSkin(); IGUIFont* font = env->getFont("../../media/fonthaettenschweiler.bmp"); if (font) skin->setFont(font); skin->setFont(env->getBuiltInFont(), EGDF_TOOLTIP);
Aggiungiamo i tre pulsanti. Il primo chiude l'engine. Il secondo crea una finestra e il terzo apre una finestra di dialogo. Il terzo parametro è l'id del pulsante, con cui potremo facilmente identificarlo quando saremo nell'event receiver.
Codice PHP: 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");
Ora aggiungiamo un'etichetta testo e una scrollbar che modichi la trasparenza di tutti gli elementi della GUI. Impostiamo il valore massimo della scrollbar a 255, perché è il massimo che il valore dei colori può assumere. Quindi creiamo l'etichetta di test e una listbox.
Codice PHP: 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());
// set scrollbar position to alpha value of an arbitrary element 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));
// Store the appropriate data in a context structure. SAppContext context; context.device = device; context.counter = 0; context.listbox = listbox;
// Then create the event receiver, giving it that context structure. MyEventReceiver receiver(context);
// And tell the device to use our custom event receiver. device->setEventReceiver(&receiver);
Alla fine creiamo un simpatico logo dell'Irrlicht Engine in alto a sinistra.
Codice PHP: env->addImage(driver->getTexture("../../media/irrlichtlogo2.png"), position2d<int>(10,10));
Questo è tutto, non resta che disegnare tutto quanto.
Codice PHP: while(device->run() && driver) if (device->isWindowActive()) { driver->beginScene(true, true, SColor(0,200,200,200));
env->drawAll(); driver->endScene(); }
device->drop();
return 0; }
Versione pdf da scaricare QUI
RE: Tutorial 5 - User Interface - Master Gabriel - 10-08-2015
Grazie Chip, appena ho tempo scarico codeblocks e provo a cavarci fuori qualcosa
|