A new custom GUI Element, based on the Irrlicht GUI Window, with these features : - Close behavior (nothing, remove, set visible false), - Configurable system buttons, - Minimize button, - Double click on minimized window maximizes it, - Restore button shows up when window is minimized, - Pinned button, to prevent moving the window, - Programmable user buttons, with attributes (show/hide for each window state) and user sprite bank, posting event catched by the user defined EventReceiver, - Double click on window bar hides window client area, - Window frame renderer using cursor coordinates as light source) and default/user skin. - Configurable minimized window position, - Flag preventing window minimizing, - Notification system, making the tittle bar to blink.
/** Example 005 User Interface This tutorial shows how to use the built in User Interface of the Irrlicht Engine. It will give a brief overview and show how to create and use windows, buttons, scroll bars, static texts, and list boxes. As always, we include the header files, and use the irrlicht namespaces. We also store a pointer to the Irrlicht device, a counter variable for changing the creation position of a window, and a pointer to a listbox. */ #include <irrlicht.h> //#include "driverChoice.h" #include "CGUIAdvancedWindow.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 /// \todo add check box to select the close behavior of the next created window /// \todo make a lsit of current window /// \todo make a button to set visible all window and set invisible /// \todo make a button to close all, to remove all, to minimize all // 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; IVideoDriver *driver; s32 counter; IGUIListBox* listbox; CGUIAdvancedWindow* last; }; // 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, GUI_ID_WINDOW_SPECIAL_BUTTON, GUI_ID_NOTIFY_WINDOW }; /* The Event Receiver is not only capable of getting keyboard and mouse input events, but also events of the graphical user interface (gui). There are events for almost everything: Button click, Listbox selection change, events that say that a element was hovered and so on. To be able to react to some of these events, we create an event receiver. We only react to gui events, and if it's such an event, we get the id of the caller (the gui element which caused the event) and get the pointer to the gui environment. */ 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) { /* If a scrollbar changed its scroll position, and it is 'our' scrollbar (the one with id GUI_ID_TRANSPARENCY_SCROLL_BAR), then we change the transparency of all gui elements. This is a very easy task: There is a skin object, in which all color settings are stored. We simply go through all colors stored in the skin and change their alpha value. */ 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; /* If a button was clicked, it could be one of 'our' three buttons. If it is the first, we shut down the engine. If it is the second, we create a little window with some text on it. We also add a string to the list box to log what happened. And if it is the third button, we create a file open dialog, and add also this as string to the list box. That's all for the event receiver. */ 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"); core::array<CGUIAdvancedWindow::buttoninfo> ButtonInfo; CGUIAdvancedWindow::buttoninfo CloseButton; CloseButton.Type = EWBT_CLOSE; CloseButton.VisibleWhenNormal = true; CloseButton.VisibleWhenBar = true; CloseButton.VisibleWhenMinimized = false; ButtonInfo.push_back(CloseButton); CGUIAdvancedWindow::buttoninfo MinimizeButton; MinimizeButton.Type = EWBT_MINIMIZE; ButtonInfo.push_back(MinimizeButton); CGUIAdvancedWindow::buttoninfo PinButton; PinButton.Type = EWBT_PIN; PinButton.VisibleWhenNormal = true; PinButton.VisibleWhenBar = true; PinButton.VisibleWhenMinimized = false; ButtonInfo.push_back(PinButton); CGUIAdvancedWindow::buttoninfo MySpecialButton; MySpecialButton.Type = EWBT_USER_DEFINED; IGUISpriteBank* bank = env->getSpriteBank("SpecialButton"); if(!bank) { bank = env->addEmptySpriteBank("SpecialButton"); bank->addTextureAsSprite(Context.driver->getTexture("../../media/reload16.png")); Context.driver->makeColorKeyTexture(Context.driver->getTexture("../../media/reload16.png"), position2di(0,0)); } MySpecialButton.Sprite = bank; MySpecialButton.SpriteIndex = 0; MySpecialButton.VisibleWhenNormal = true; MySpecialButton.VisibleWhenBar = false; MySpecialButton.VisibleWhenMinimized = false; MySpecialButton.Name = L""; MySpecialButton.ToolTipText = L"My Special Button !"; MySpecialButton.UserEventId = GUI_ID_WINDOW_SPECIAL_BUTTON; ButtonInfo.push_back(MySpecialButton); CGUIAdvancedWindow* window = new CGUIAdvancedWindow( env, env->getRootGUIElement(), -1, rect<s32>(100 + (30*Context.counter)%200, 100 + (30*Context.counter)%200, 300 + (30*Context.counter)%200, 200 + (30*Context.counter)%200), ButtonInfo, irr::gui::EWC_REMOVE, core::position2di((Context.counter*200)%600,455-22*(Context.counter/3)), Context.device->getCursorControl() ); window->setText(L"New Advanced Window"); env->addStaticText(L"Please close me", rect<s32>(35,35,140,50), true, // border? false, // wordwrap? window); Context.last = window; ++Context.counter; } 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; case GUI_ID_WINDOW_SPECIAL_BUTTON: Context.listbox->addItem(L"Click on Window SPECIAL BUTTON!"); return true; case GUI_ID_NOTIFY_WINDOW: Context.last->notify(false); 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, now for the more interesting part. First, create the Irrlicht device. As in some examples before, we ask the user which driver he wants to use for this example: */ 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)); IrrlichtDevice * device = createDevice(EDT_OPENGL , core::dimension2d<u32>(640, 480)); if (device == 0) return 1; // could not create selected driver. /* The creation was successful, now we set the event receiver and store pointers to the driver and to the gui environment. */ device->setWindowCaption(L"Irrlicht Engine - User Interface Demo"); device->setResizable(true); video::IVideoDriver* driver = device->getVideoDriver(); IGUIEnvironment* env = device->getGUIEnvironment(); /* To make the font a little bit nicer, we load an external font and set it as the new default font in the skin. To keep the standard font for tool tip text, we set it to the built-in font. */ IGUISkin* skin = env->getSkin(); IGUIFont* font = env->getFont("../../media/fonthaettenschweiler.bmp"); if (font) skin->setFont(font); skin->setFont(env->getBuiltInFont(), EGDF_TOOLTIP); /* We add three buttons. The first one closes the engine. The second creates a window and the third opens a file open dialog. The third parameter is the id of the button, with which we can easily identify the button in the event receiver. */ 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"); env->addButton(rect<s32>(10,360,110,360 + 32), 0, GUI_ID_NOTIFY_WINDOW, L"Notify", L"Notif the last window"); /* Now, we add a static text and a scrollbar, which modifies the transparency of all gui elements. We set the maximum value of the scrollbar to 255, because that's the maximal value for a color value. Then we create an other static text and a list box. */ 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); // 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.driver = driver; 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); /* And at last, we create a nice Irrlicht Engine logo in the top left corner. */ env->addImage(driver->getTexture("../../media/irrlichtlogo2.png"), position2d<int>(10,10)); /* That's all, we only have to draw everything. */ while(device->run() && driver) if (device->isWindowActive()) { driver->beginScene(true, true, SColor(0,200,200,200)); env->drawAll(); driver->endScene(); } device->drop(); return 0; } /* **/
You need to login to post a comment.
