Skip to main content

09 Hello Controls

With the substantial increase in content in modern applications, the performance of the user interface has become crucial. Tellusim Controls system manages all user interfaces, offering excellent performance alongside a comprehensive set of extendable and customizable controls (widgets). Tellusim Canvas layer provides a rendering backend, while the Controls layer handles the UI logic. All features of the Canvas layer, such as cross-platform support, high performance, resolution-independent rendering, and customization, are fully integrated into the Controls layer.

Controls require a Canvas instance since it is responsible for rendering. The ControlRoot acts as the primary control, managing the hierarchy of controls while handling resources and input. Multiple ControlRoot instances can exist within an application, for example, in multi-window applications or for 3D controls. Basic resources, including fonts and textures, can be embedded within the binary. The following code demonstrates the initialization of controls and the translation of basic events in C++:

// create root control
ControlRoot root(canvas, true);

// keyboard callbacks
window.setKeyboardPressedCallback([&](uint32_t key, uint32_t code) {
if(root) root.setKeyboardKey(translate_key(key, true), code, true);
});
window.setKeyboardReleasedCallback([&](uint32_t key) {
if(root) root.setKeyboardKey(translate_key(key, false), 0, false);
});

Key and mouse button translation is required because controls utilize their own set of event parameters. This design allows controls to be embedded in different applications with their own events.

The controls update loop is straightforward and should be executed before Canvas::create() method:

// update controls
root.setViewport(width, height);
root.setMouse(mouse_x, mouse_y, translate_button(window.getMouseButtons()));
root.setMouseAxis(Control::AxisY, window.getMouseAxis(Window::AxisY));
while(root.update(canvas.getScale(target))) { }

// create canvas resource
if(!canvas.create(device, target)) return false;

Multiple calls to Controls::update() are necessary because resize and callback actions may take a few frames to stabilize the layout.

That concludes the required steps for initialization and rendering. We can now create the actual control widgets. The basic set of controls includes:

The controls element forms a hierarchy where container controls are responsible for placement and event propagation, while leaf controls handle user events. Below is the instantiation of ControlDialog, along with custom styling that incorporates stroke and gradient effects:

// create dialog
ControlDialog dialog(&root, 1, 0.0f, 8.0f);
dialog.setAlign(Control::AlignCenter);
dialog.setGradientStyle(GradientStyle(2.0f, Vector2f(0.0f, 1.0f), Color::magenta, Color::blue));
dialog.setStrokeStyle(StrokeStyle(2.0f, Color(0.6f, 0.5f)));
dialog.setMode(CanvasElement::ModeGradient);
dialog.setColor(Color::gray);

There are two types of event processing: one involves checking the control state in the main loop, while the preferred method is to assign control-specific callback handlers.

This WebGL/GPU manual example is available on GitHub and includes main Control widgets and Callback processing:

Interface plugins are control extensions provided with full source code, enabling complete customization and modification. Below is a list of the interface plugins included in the Tellusim SDK:

Tellusim Explorer showcases all aspects of the control system and serves as an excellent demonstration of its features: