Customizing Menu
The VR template has two menu types: the main one is attached to the HMD position, and the second — to the hand. In the VR sample, the head_menu node (ObjectGui) is used for the main menu, and the hand_menu node (ObjectGui) is used for the additional menu.
Hand- and head-mounted menu nodes have the MixedRealityMenuGui and HandMenuSampleGui components assigned respectively. Both these components are inherited from the base MenuBaseUI component that implements a user interface. In general, the user interface is implemented as follows:
- Inherit a new component from the base MenuBaseUI.
- Implement the user interface with the required widgets in the overridden init_gui() method.
- Implement handlers for processing widgets events (pressing a button, selecting elements in the drop-down menu, etc.).
- Subscribe the corresponding widgets for the events in the init_gui() method.
- Assign the component to the ObjectGui node that will display the user interface.
Let's create a new menu for the left controller and add the quit button:
-
Inherit a new component from the base MenuBaseUI, call it VRHandMenu and copy the following code to it:
#pragma once #include <UnigineComponentSystem.h> #include <UnigineGui.h> #include "../Demo/GUI/MenuBaseUI.h" class VRHandMenu : public MenuBaseUI { public: COMPONENT_DEFINE(VRHandMenu, MenuBaseUI); // инициализация UI (создание виджетов и т.д.) virtual void init_gui() override; private: // объявляем обработчики событий void button_quit_clicked(); void ok_clicked(); void cancel_clicked(); void window_changed(); // ObjectGui background Unigine::WidgetSpritePtr background; // объявляем нужные виджеты Unigine::WidgetVBoxPtr VBox; Unigine::WidgetButtonPtr quitButton; Unigine::WidgetWindowPtr window; Unigine::WidgetButtonPtr okButton; Unigine::WidgetButtonPtr cancelButton; Unigine::WidgetHBoxPtr HBox; };
#include "VRHandMenu.h" REGISTER_COMPONENT(VRHandMenu); using namespace Unigine; using namespace Math; const int font_size = 25; void VRHandMenu::init_gui() { if (!gui) return; // backgound background = WidgetSprite::create(gui, "core/textures/common/black.texture"); background->setColor(Math::vec4(1.0f, 1.0f, 1.0f, 0.5f)); gui->addChild(background, Gui::ALIGN_BACKGROUND | Gui::ALIGN_EXPAND); // добавляем в GUI контейнер WidgetVBox с вертикальным расположением виджетов VBox = WidgetVBox::create(); VBox->setWidth(gui->getWidth()); VBox->setHeight(100); gui->addChild(VBox, Gui::ALIGN_OVERLAP | Gui::ALIGN_CENTER); // добавляем в контейнер кнопку, отображающую окно подтверждения выхода из приложения quitButton = WidgetButton::create(gui, "QUIT APPLICATION"); quitButton->setFontSize(20); VBox->addChild(quitButton); quitButton->getEventClicked().connect(this, &VRHandMenu::button_quit_clicked); VBox->arrange(); // создаем окно подтверждения выхода из приложения window = WidgetWindow::create(gui, "Quit Application"); window->setFontSize(20); // добавляем в окно контейнер WidgetHBox с горизонтальным расположением виджетов HBox = WidgetHBox::create(); HBox->setWidth(window->getWidth()); HBox->setHeight(100); window->addChild(HBox); // добавляем в контейнер кнопку 'OK' c обработчиком 'OkClicked', закрывающим приложение okButton = WidgetButton::create(gui, "OK"); okButton->setFontSize(20); HBox->addChild(okButton); okButton->getEventClicked().connect(this, &VRHandMenu::ok_clicked); // добавляем в контейнер кнопку 'Cancel' c обработчиком 'CancelClicked', закрывающим окно подтверждения cancelButton = WidgetButton::create(gui, "Cancel"); cancelButton->setFontSize(20); HBox->addChild(cancelButton); cancelButton->getEventClicked().connect(this, &VRHandMenu::cancel_clicked); } void VRHandMenu::button_quit_clicked() { gui->addChild(window, Gui::ALIGN_OVERLAP | Gui::ALIGN_CENTER); } void VRHandMenu::ok_clicked() { Engine::get()->quit(); } void VRHandMenu::cancel_clicked() { gui->removeChild(window); } void VRHandMenu::window_changed() { // do not let the window go beyond the gui plane int x = Math::clamp(window->getPositionX(), 0, window->getGui()->getWidth() - window->getWidth()); int y = Math::clamp(window->getPositionY(), 0, window->getGui()->getHeight() - window->getHeight()); window->setPosition(x, y); }
-
Save these files and then build and run the application by hitting Ctrl + F5 to make the Component System generate a property to be used to assign the component to nodes. Close the application after running it and switch to UnigineEditor.
Then assign the VRHandMenu property to the hand_menu node. And disable the HandMenuSampleGui property which is assigned to this node by default.
-
Save changes (Ctrl+S) and run your application via SDK Browser.
After launching the application, press the Menu button on the left controller — the result will look similar to this: