The Polycode User Interface Module has many elements as windows, text input fields, check boxes, buttons, etc. It is completely written in Polycode and is used in the Polycode IDE.

Contents

UI overview.

All elements of the UI Module are based on the UIElement class which is just an Entity with some extra methods needed for the user interface. These methods are mainly for dragging, focusing and resizing the element.

The elements in UI module are:

  • UIRect
  • UIImage
  • UILabel and UIMultilineLabel
  • UIBox
  • UICheckBox
  • UIComboBox
  • UIButton and UIImageButton
  • UIScrollContainer
  • UIHScrollBar and UIVScrollbar
  • UIHSizer and UIVSizer
  • UITreeContainer and UITrees
  • UITextInput
  • UIWindow
  • UIColorPicker
  • UIFileDialog

Creating a basic user interface.

Before you can use any of the UI elements in C++ you have to link to the PolycodeUI library, include PolycodeUI.h and load an UITheme. Lua loads the default theme out-of-the-box. There are two UIThemes shipped with Polycode called default and dark in Assets/UIThemes.pak. You need to add the archive and then load the configuration file of your theme. For both themes there's also a retina version which you have to load manually when using a retina display. To choose a theme just replace the folder name default with dark or default_retina or dark_retina respectively. For C++ you have to copy the UIThemes.pak to your execution folder.

C++
CoreServices::getInstance()->getResourceManager()->addArchive("UIThemes.pak");
CoreServices::getInstance()->getConfig()->loadConfig("Polycode", "UIThemes/default/theme.xml");
To use the dark theme in Lua use this line:
Lua
Services.Config:loadConfig("Polycode", "UIThemes/dark/theme.xml")

Normally the User Interface elements are added to their own Scene as it needs to be in a SCENE_2D_TOPLEFT scene (see Scene types). This works just as you would add any other Entity to a Scene. To have your text rendered nicely and sharply and not a bit washy you also have to set the texture filtering mode to TEX_FILTERING_NEAREST.

C++
Services()->getRenderer()->setTextureFilteringMode(Renderer::TEX_FILTERING_NEAREST);
Scene *scene = new Scene(Scene::SCENE_2D_TOPLEFT);
UILabel *label = new UILabel("Hello, World!", 64, "sans", Label::ANTIALIAS_FULL);
scene->addChild(label);
Lua
Services.Renderer:setTextureFilteringMode(Renderer.TEX_FILTERING_NEAREST)
scene = Scene(Scene.SCENE_2D_TOPLEFT)
label = UILabel("Hello, World!", 64, "sans", Label.ANTIALIAS_FULL)
scene:addChild(label)

When the UI module was just for displaying text it was useless as a SceneLabel could do that job either - but the UI module also adds UIButtons and much more! Let's have a look how simple you can make use of a button: First we have to enable input event processing for the scene. Then we create a new UIButton, add it to our scene and add an EventListener to the button (see Events).

C++
scene->rootEntity.processInputEvents = true;
UIButton* button = new UIButton("Press me!", 80);
button->setPosition(5, 70);
scene->addChild(button);
button->addEventListener(this, UIEvent::CLICK_EVENT);
Lua
scene.rootEntity.processInputEvents = true
button = UIButton("Press me!", 80)
button:setPosition(5, 70)
scene:addChild(button)
button:addEventListener(nil, onButtonPress, UIEvent.CLICK_EVENT)

Let's assume that you have some options for your application and you want users to be able to just press return to apply the changes. Then you can use addFocusChild instead of addChild.

Using UIWindows and UITextInputs.

As you have learned some basics now just let's go one step further: Using UIWindows and UITextInputs. Firstly we create a window specifying the caption and size of the window. Then we add the window as usually to our scene. Now we have a simple draggable and closable window. To (re-)show the window in the code use showWindow - to hide use hideWindow.

We can add some stuff to the window as well. Let's add a UILabel, a UITextInput and a UIButton. To get the UITextInput working all-right, we have to initialize some static variables from SceneLabel. To achieve the best results we set the position of the elements in the window to the padding of the window.

C++
SceneLabel::defaultAnchor = Vector3(-1.0, -1.0, 0.0);
SceneLabel::defaultPositionAtBaseline = true;
SceneLabel::defaultSnapToPixels = true;
SceneLabel::createMipmapsForLabels = false;

UIWindow *window = new UIWindow("Who are you?", 200, 200);
scene->addChild(window);

UILabel *name = new UILabel("Enter your Name:", 14, "sans", Label::ANTIALIAS_FULL);
name->setPosition(window->padding, window->topPadding);
window->addChild(name);

UITextInput *nameInput = new UITextInput(false, 180, 12);
nameInput->setPosition(window->padding, window->topPadding + 18);
window->addChild(nameInput);

UIButton *okButton = new UIButton("OK!", 40);
okButton->setPosition(window->padding, window->topPadding + 45);
window->addChild(okButton);
Lua
SceneLabel.defaultAnchor = Vector3(-1.0, -1.0, 0.0)
SceneLabel.defaultPositionAtBaseline = true
SceneLabel.defaultSnapToPixels = true
SceneLabel.createMipmapsForLabels = false

window = UIWindow("Who are you?", 200, 200)
scene:addChild(window)

name = UILabel("Enter your Name:", 14, "sans", Label.ANTIALIAS_FULL)
name:setPosition(window.padding, window.topPadding)
window:addChild(name)

nameInput = UITextInput(false, 180, 12)
nameInput:setPosition(window.padding, window.topPadding+18)
window:addChild(nameInput)

okButton = UIButton("OK!", 40)
okButton:setPosition(window.padding, window.topPadding+45)
window:addChild(okButton)