[ Новые сообщения · Участники · Правила форума · Поиск · RSS ]
  • Страница 1 из 1
  • 1
Форум » Игровые движки » IrrLicht Engine » Туториал №5 Пользовательский интерфейс
Туториал №5 Пользовательский интерфейс
MerGC_TeamДата: Среда, 02.04.2014, 22:01 | Сообщение # 1
Веселый админ
Группа: Администраторы
Сообщений: 32
Статус: Оффлайн
В движке IrrLicht наличествуется практически весь необходимый набор функций для реализации пользовательского интерфейса. В этом примере я раскажу как создать окошко, кнопку, полосу прокрутки, статический текст, список.

Начнем как обычно, подключим заголовочный файл и объявим пространство имен 'irr' и все его подпространства. и сообщаем линкеру о необходимости подключить библиотеку irrlicht.lib движка.

Код
#include < irrlicht.h >
#include "driverChoice.h"

using namespace irr;

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

// Объявим структуру, которую передадим в наш класс приемник событий через конструктор
// и которую будем использовать в методе OnEvent() для обратной связи с движком
struct SAppContext
{
         IrrlichtDevice *device; // указатель на корневой объект
         s32 counter; // счетчик  
         IGUIListBox*    listbox; // указатель на GUI элемент - список
};

// Определим несколько уникальных идентификаторов для наших gui элементов.
enum
{
         GUI_ID_QUIT_BUTTON = 101, // id кнопки выхода из приложения
         GUI_ID_NEW_WINDOW_BUTTON, // id кнопки создания нового окна
         GUI_ID_FILE_OPEN_BUTTON, // id кнопки открытия диалога для выбора файлов
         GUI_ID_TRANSPARENCY_SCROLL_BAR // id полосы прокрутки
};

В обработчик событий передаются не только события мыши и клавиатуры, но и события пользовательского интерфейса (GUI), такие как: нажатие кнопок, выбор элемента в списках, короче все события которые генерируются элементами интерфейса. Создадим класс приемник событий с методом обработчиком. В этом обработчике мы проверяем принадлежность события к событиям GUI, потом получаем идентификатор элемента, который сгенерировал событие и по идентификатору получим ссылку на сам элемент интерфейса.

Код
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) // обрабатываем события относительно типа
                         {


Если сдвинули бегунок на полосе прокрутки и это именно та полоса которую мы создали (идентификатор id будет равен предопределенному уникальному идентификатору GUI_ID_TRANSPARENCY_SCROLL_BAR), то относительно положения бегунка изменяем прозрачность всех элементов интерфейса в окне приложения. Это задача из простых, т.к. в интерфейсе есть объект skin, который хранит все параметры отображения по умолчанию для всех элементов. Мы просто пройдемся в цикле по всем значениям в этом объекте и поменяем значения для альфа-канала.

Код
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;


Если событие вызвано кликом по кнопке, то опять же сверяем идентификатор id с предопределенными идентификаторами, чтобы определить логическое назначение кнопки, потом обрабатываем и записываем в лог (элемент интерфейса "список") некоторый текст касательно события.

Код
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"); // запись в "лог"
                    env->addFileOpenDialog(L"Please choose a file.");
                    return true;

                    default:
                    return false;
                    }
                    break;

                         default:
                    break;
                         }
                 }

                 return false;
         }

private:
         SAppContext & Context;
};


С обрабочиком событий все! Спрашиваем у пользователя перед созданием движка какой драйвер он желает использовать. Создаем коневой объект(движок):

Код
int main()
{
          
         // спрашиваем пользователя про драйвер (OpenGL, DirectX...)
         video::E_DRIVER_TYPE driverType=driverChoiceConsole();
         if (driverType==video::EDT_COUNT) return 1; // драйвер не выбран, выходим

         // создаем движок
         IrrlichtDevice * device = createDevice(driverType, core::dimension2d< u32 >(640, 480));
         if (device == 0)  return 1; // ошибка при создании, выходим


Устанавливаем заголовок окна и создаем пару вспомогательных указателя на драйвер(driver) и gui среду(env)

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

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


Чтобы шрифт был покрасивши, мы загрузим свой шрифт и объявим его используемым по умолчанию, вместо встроенного в движок.

Код
IGUISkin* skin = env->getSkin();
         IGUIFont* font = env->getFont("../../media/fonthaettenschweiler.bmp"); // грузим шрифт
         if (font) skin->setFont(font); // ставим наш шрифт, как основной

         skin->setFont(env->getBuiltInFont(), EGDF_TOOLTIP); // для всплывающих подсказок переназначаем шрифт на встроенный


Добавляем три кнопки. Одну для закрытия приложения, вторую для создания окошка, третью для создания файлового диалога. Третьим параметром каждого вызова создания кнопки будет уникальный идентификатор который мы определили ранее, чтобы можно было определить логическое назначение кнопки.

Код
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");


Добавляем полосу прокрутки отвечающую за степень прозрачности нашего интерфейса. Значения для полосы будут варьироваться от 0 до 255, т.к. это и есть диапазон значений для альфа-канала. И также создадим элементы статического текста для меток и элемент "список".

Код
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);

         // устанавливаем положение бегунка равным текущему значению в альфа-канале для элементов gui
         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));

         // Создаем структуру, которую передадим в наш обработчик событий для обратной связи с движком
         SAppContext context;
         context.device = device;
         context.counter = 0;
         context.listbox = listbox;

         // Создаем обработчик событий.
         MyEventReceiver receiver(context);

         // Назначаем движку наш обработчик
         device->setEventReceiver(&receiver);


Ну и картина была бы неполной без логотипа IrrLicht - поэтому добавляем

Код
env->addImage(driver->getTexture("../../media/irrlichtlogo2.png"), position2d< s32 >(10,10));


Реализуем главный цикл.

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

                 env->drawAll(); // т.к. кроме элементов интерфейса ничего нет, то рисуем только их
          
                 driver->endScene();
         }

         // по выходу из главного цикла, прибиваем движок
         device->drop();

         return 0;
}


Компилируем, запускаем, проверяем работу интерфейса.
 
Форум » Игровые движки » IrrLicht Engine » Туториал №5 Пользовательский интерфейс
  • Страница 1 из 1
  • 1
Поиск: