Capixo Posted Saturday at 03:53 AM Posted Saturday at 03:53 AM Probably a very basic question, please forgive me. How do you use Unigine's C++ workflow to create a menu page (the kind of game start page that fills the screen in 2D)? I created two files, MainMenu.h and MainMenu.cpp, but I don't know how to get the UNIGINE-built game runtime to load this page first and show two buttons with click-to-interact logic. Also, I have doubts about parameters; a YouTube tutorial shows that the parameters under Dummynode in his editor have some of his properties, but I can't do that. Can anyone help me? Thank you.
fox Posted Monday at 06:00 PM Posted Monday at 06:00 PM Hi, @Capixo! Here is a simple example of the start menu implemented in a C++ component. With a complete step-by-step instruction on how to use it. 1. Open Project in IDE First, open your project in an IDE (Microsoft Visual Studio is recommended) - go to SDK Browser and choose Open Code IDE on your project's card. 2. Add New C++ Component Class In an IDE create a new C++ class (Project → Add Class) and call it StartMenu. Make sure it inherits from the ComponentBase class. You can build a whole hierarchy using your own components, by inheriting some components from others in accordance with the OOP principles (we'll review this in detail later). Two files StartMenu.h and StartMenu.cpp will be added to your C++ project. 3. Write Component Code Copy and paste the following code to the StartMenu.h and StartMenu.cpp files. StartMenu.h #pragma once #include <UnigineComponentSystem.h> #include <UnigineGui.h> class StartMenu : public Unigine::ComponentBase { public: // component constructor and the list of methods COMPONENT_DEFINE(StartMenu, ComponentBase); // ------------------------------- COMPONENT_INIT(init); COMPONENT_SHUTDOWN(shutdown); Unigine::WidgetSpritePtr bgimage = nullptr; Unigine::WidgetVBoxPtr vbox = nullptr; PROP_PARAM(String, menuTitle, "Start Menu", "Menu Title"); PROP_PARAM(Int, menuFontSize, 30, "Font size"); PROP_PARAM(File, bgImage, "Background Image"); PROP_PARAM(Color, bgColor, Unigine::Math::vec4(0.1f, 0.8f, 0.1f, 0.7f), "Background Color"); private: // auxiliary variable used to manage event subscriptions Unigine::EventConnections econn; // proxy-handlers calling handlers according to subscriptions void onStartClicked(); void onQuitClicked(); protected: // main loop overrides void init(); void shutdown(); }; StartMenu.cpp #include "StartMenu.h" REGISTER_COMPONENT(StartMenu); using namespace Unigine; using namespace Math; // component initialization method void StartMenu::init() { GuiPtr screenGui = Gui::getCurrent(); // creating a background image and a vbox-container for the menu bgimage = WidgetSprite::create(screenGui, Unigine::FileSystem::guidToPath(FileSystem::getGUID(bgImage.getRaw()))); bgimage->setLifetime(Widget::LIFETIME_WORLD); vbox = WidgetVBox::create(screenGui); vbox->setPermanentFocus(); vbox->setLifetime(Widget::LIFETIME_WORLD); vbox->setWidth(200); // configuring the background for the menu vbox->setBackground(1); vbox->setBackgroundColor(bgColor); // Creating a menu title and two buttons WidgetLabelPtr title_label = WidgetLabel::create(screenGui, menuTitle); title_label->setFontSize(menuFontSize); title_label->setTextAlign(Gui::ALIGN_CENTER); WidgetButtonPtr button_start = WidgetButton::create(screenGui, "Start the Game"); WidgetButtonPtr button_exit = WidgetButton::create(screenGui, "Quit"); // subscribing to click events for both buttons button_start->getEventClicked().connect(econn, this, &StartMenu::onStartClicked); button_exit->getEventClicked().connect(econn, this, &StartMenu::onQuitClicked); // adding a title and buttons to the menu vbox->addChild(title_label); vbox->addChild(WidgetSpacer::create(screenGui)); vbox->addChild(button_start); vbox->addChild(button_exit); vbox->addChild(WidgetSpacer::create(screenGui)); // adding a background sprite and the menu to the Engine GUI screenGui->addChild(bgimage, Gui::ALIGN_BACKGROUND | Gui::ALIGN_EXPAND); screenGui->addChild(vbox, Gui::ALIGN_OVERLAP | Gui::ALIGN_CENTER); } void StartMenu::shutdown() { // removing all event subscriptions econn.disconnectAll(); } // handler to be executed on clicking the Start button void StartMenu::onStartClicked() { vbox->removeFocus(); vbox->setHidden(true); bgimage->setHidden(true); Input::setMouseGrab(true); ControlsApp::setMouseEnabled(true); // start the game } // handler to be executed on clicking the Quit button void StartMenu::onQuitClicked() { // quit the application Engine::get()->quit(); } 4. Compile And Run To Generate Property Don't forget to set the appropriate platform and configuration settings for your project before compiling your code in Visual Studio. Build and run your application by hitting Ctrl + F5 to make the Component System register the component and generate an associated property with the corresponding set of parameters (according to your component's class declaration) to be used to assign the component to nodes. Close the application after running it and switch to UnigineEditor. 5. Assign Component To Nodes In Editor After successful registration all available properties associated with your C++ components are displayed in the Properties window as children of the basic node_base property. The component is ready, but now it must be assigned to some node, otherwise its code won't be executed. Create a new NodeDummy, select it, then add the StartMenu property to it via the Parameters window (Add New Property button). In the Parameters window set the desired background image, title text and font size, and save the world by hitting Ctrl + S. Now, you can launch your application via the SDK Browser by selecting the project on the Projects tab and clicking Run. But first, make sure, that appropriate Customize Run Options (Debug version in our case) are selected, by clicking an ellipsis under the Run button (check Debug and Remember then click Run). Check if the menu works as intended! Should look somewhat like this: Hope this helps! 1
Capixo Posted Tuesday at 01:37 AM Author Posted Tuesday at 01:37 AM Hello, @fox 7 hours ago, fox said: Hi, @Capixo! Here is a simple example of the start menu implemented in a C++ component. With a complete step-by-step instruction on how to use it. 1. Open Project in IDE First, open your project in an IDE (Microsoft Visual Studio is recommended) - go to SDK Browser and choose Open Code IDE on your project's card. 2. Add New C++ Component Class In an IDE create a new C++ class (Project → Add Class) and call it StartMenu. Make sure it inherits from the ComponentBase class. You can build a whole hierarchy using your own components, by inheriting some components from others in accordance with the OOP principles (we'll review this in detail later). Two files StartMenu.h and StartMenu.cpp will be added to your C++ project. 3. Write Component Code Copy and paste the following code to the StartMenu.h and StartMenu.cpp files. StartMenu.h #pragma once #include <UnigineComponentSystem.h> #include <UnigineGui.h> class StartMenu : public Unigine::ComponentBase { public: // component constructor and the list of methods COMPONENT_DEFINE(StartMenu, ComponentBase); // ------------------------------- COMPONENT_INIT(init); COMPONENT_SHUTDOWN(shutdown); Unigine::WidgetSpritePtr bgimage = nullptr; Unigine::WidgetVBoxPtr vbox = nullptr; PROP_PARAM(String, menuTitle, "Start Menu", "Menu Title"); PROP_PARAM(Int, menuFontSize, 30, "Font size"); PROP_PARAM(File, bgImage, "Background Image"); PROP_PARAM(Color, bgColor, Unigine::Math::vec4(0.1f, 0.8f, 0.1f, 0.7f), "Background Color"); private: // auxiliary variable used to manage event subscriptions Unigine::EventConnections econn; // proxy-handlers calling handlers according to subscriptions void onStartClicked(); void onQuitClicked(); protected: // main loop overrides void init(); void shutdown(); }; StartMenu.cpp #include "StartMenu.h" REGISTER_COMPONENT(StartMenu); using namespace Unigine; using namespace Math; // component initialization method void StartMenu::init() { GuiPtr screenGui = Gui::getCurrent(); // creating a background image and a vbox-container for the menu bgimage = WidgetSprite::create(screenGui, Unigine::FileSystem::guidToPath(FileSystem::getGUID(bgImage.getRaw()))); bgimage->setLifetime(Widget::LIFETIME_WORLD); vbox = WidgetVBox::create(screenGui); vbox->setPermanentFocus(); vbox->setLifetime(Widget::LIFETIME_WORLD); vbox->setWidth(200); // configuring the background for the menu vbox->setBackground(1); vbox->setBackgroundColor(bgColor); // Creating a menu title and two buttons WidgetLabelPtr title_label = WidgetLabel::create(screenGui, menuTitle); title_label->setFontSize(menuFontSize); title_label->setTextAlign(Gui::ALIGN_CENTER); WidgetButtonPtr button_start = WidgetButton::create(screenGui, "Start the Game"); WidgetButtonPtr button_exit = WidgetButton::create(screenGui, "Quit"); // subscribing to click events for both buttons button_start->getEventClicked().connect(econn, this, &StartMenu::onStartClicked); button_exit->getEventClicked().connect(econn, this, &StartMenu::onQuitClicked); // adding a title and buttons to the menu vbox->addChild(title_label); vbox->addChild(WidgetSpacer::create(screenGui)); vbox->addChild(button_start); vbox->addChild(button_exit); vbox->addChild(WidgetSpacer::create(screenGui)); // adding a background sprite and the menu to the Engine GUI screenGui->addChild(bgimage, Gui::ALIGN_BACKGROUND | Gui::ALIGN_EXPAND); screenGui->addChild(vbox, Gui::ALIGN_OVERLAP | Gui::ALIGN_CENTER); } void StartMenu::shutdown() { // removing all event subscriptions econn.disconnectAll(); } // handler to be executed on clicking the Start button void StartMenu::onStartClicked() { vbox->removeFocus(); vbox->setHidden(true); bgimage->setHidden(true); Input::setMouseGrab(true); ControlsApp::setMouseEnabled(true); // start the game } // handler to be executed on clicking the Quit button void StartMenu::onQuitClicked() { // quit the application Engine::get()->quit(); } 4. Compile And Run To Generate Property Don't forget to set the appropriate platform and configuration settings for your project before compiling your code in Visual Studio. Build and run your application by hitting Ctrl + F5 to make the Component System register the component and generate an associated property with the corresponding set of parameters (according to your component's class declaration) to be used to assign the component to nodes. Close the application after running it and switch to UnigineEditor. 5. Assign Component To Nodes In Editor After successful registration all available properties associated with your C++ components are displayed in the Properties window as children of the basic node_base property. The component is ready, but now it must be assigned to some node, otherwise its code won't be executed. Create a new NodeDummy, select it, then add the StartMenu property to it via the Parameters window (Add New Property button). In the Parameters window set the desired background image, title text and font size, and save the world by hitting Ctrl + S. Now, you can launch your application via the SDK Browser by selecting the project on the Projects tab and clicking Run. But first, make sure, that appropriate Customize Run Options (Debug version in our case) are selected, by clicking an ellipsis under the Run button (check Debug and Remember then click Run). Check if the menu works as intended! Should look somewhat like this: Hope this helps! Hello, @fox. Thank you for so much detailed step-by-step tutorial explaining. You are really so kind man. I find that in your in tutorial, you create a custom class(StartMenu class) by click 'Project-> Add Class', while I was just create cpp and head files in a new folder, MyGame/data/Scripts/StartMenu.cpp, which makes VS IDE doesn't consider it as belongs to project. However, if I put StartMenu.cpp under the folder, MyGame/source, which is folder with main.cpp together, this will lead the problem I can not find this cpp in Editor, when I want to add it to node as Script Setting. Do you know how to fix this issue? I will add some screenshots to help you understand later, due to I am not with my workstation together for now. Still thank you for your detailed explaining above.
fox Posted Tuesday at 04:04 AM Posted Tuesday at 04:04 AM Hi, @Capixo! Oh, now I see. Simply putting source files (*.cpp and *.h) to the project's folder does not automatically add it to the C++ project. To add existing files describing your component (or other sources you might need) to the project in Visual Studio you can simply right-click on your project's name in the Solution Explorer and choose Add-> Existing Item (or press Shift+Alt+A) and select your component's *.cpp and *.h files in the dialog that opens. After clicking Add both will be added to your project, so you can compile and run it to generate a property proceeding to Step 4 of the instruction given above. Hope this helps!
Capixo Posted Tuesday at 11:17 PM Author Posted Tuesday at 11:17 PM 19 hours ago, fox said: Hi, @Capixo! Oh, now I see. Simply putting source files (*.cpp and *.h) to the project's folder does not automatically add it to the C++ project. To add existing files describing your component (or other sources you might need) to the project in Visual Studio you can simply right-click on your project's name in the Solution Explorer and choose Add-> Existing Item (or press Shift+Alt+A) and select your component's *.cpp and *.h files in the dialog that opens. After clicking Add both will be added to your project, so you can compile and run it to generate a property proceeding to Step 4 of the instruction given above. Hope this helps! Thank you, it really helps a lot. 1
Recommended Posts