Table of contents
1. Setting up the WindowManager
Create a WindowManager in your application entry point, passing the RenderingWindow, a font URI, and an optional font scale and default text color. The WindowManager subscribes to engine process and input events automatically:
int lysaMain() {
lysa::ContextConfiguration contextConfiguration { };
lysa::Lysa
lysa(contextConfiguration);
"app://res/fonts/Signwood",
0.25f,
lysa::float4(1.0f, 1.0f, 1.0f, 1.0f));
auto scene = std::make_unique<nodes::GameScene>(windowManager);
lysa::ctx().events.subscribe(lysa::MainLoopEvent::PROCESS,
[&](const lysa::Event&) {
window.getRenderTarget().render();
});
return 0;
}
2. Creating a UI Window
A Window is a virtual overlay panel managed by WindowManager. Create one with a rectangle and configure its style and root widget before adding child widgets:
const auto uiWindow = windowManager.create(lysa::RECT_FULLSCREEN);
const auto dialog = windowManager.create(lysa::Rect{100.0f, 100.0f, 400.0f, 300.0f});
dialog->setResizeableBorders(
dialog->setMinimumSize(200.0f, 150.0f);
Subclass Window to respond to lifecycle events:
public:
HUDWindow() : Window(
lysa::RECT_FULLSCREEN) {}
}
}
};
const auto hud = windowManager.add(std::make_shared<HUDWindow>());
3. Creating and adding widgets
Use the create<T>() template on a Window or Widget to construct and add a child in one step. The first argument is a resource string (size or style hint), the second is the Alignment:
Widgets can also be constructed separately and added with add<T>():
auto label = std::make_shared<lysa::ui::Text>("Score: 0");
label->setTextColor(lysa::float4{1.0f, 1.0f, 0.0f, 1.0f});
Remove a specific child or clear the entire tree:
4. Alignment and layout
The Alignment enum controls how each child is stacked inside its parent's content area. Children are laid out in the order they are added.
Use padding to add space between stacked children:
Use borders to add internal margins inside a widget:
panel->setHBorder(10.0f);
5. Handling events
All widget signals are dispatched through the engine's event system. Subscribe using the widget's id and a UIEvent constant:
[](const lysa::Event&) {
lysa::Log::info("Button clicked!");
});
[editField](const lysa::Event& e) {
const auto& payload = static_cast<const lysa::ui::UIEventText&>(e);
lysa::Log::info("New text: " + payload.text);
});
[](const lysa::Event& e) {
const auto& payload = static_cast<const lysa::ui::UIEventValue&>(e);
lysa::Log::info("Value: " + std::to_string(payload.value));
});
6. Text widget
Text displays a single immutable line of text. Wrap it inside a Box or Button for a bordered appearance:
label->setFontScale(1.5f);
label->setText("Health: 75");
Query the natural size of a Text widget before sizing its container:
float w, h;
label->getSize(w, h);
container->setSize(w + 20.0f, h + 10.0f);
7. TextEdit widget
TextEdit provides a single-line editable text field with cursor and selection support:
edit->setText("Player One");
edit->setSelStart(0);
[edit](const lysa::Event&) {
lysa::Log::info("Input: " + edit->getText());
});
8. Image widget
Image displays a lysa::Image resource. By default it auto-sizes to the image dimensions:
const auto logo = lysa::ctx().resources.load<lysa::Image>("app://res/ui/logo.png");
icon->
setColor(lysa::float4{1.0f, 0.5f, 0.5f, 1.0f});
9. ScrollBar widget
ScrollBar (and its aliases HScrollBar / VScrollBar) lets the user select a value within a numeric range:
0.0f, 100.0f, 50.0f, 1.0f);
0.0f, 200.0f, 0.0f, 5.0f);
hBar->setMax(255.0f);
hBar->setValue(128.0f);
[hBar](const lysa::Event&) {
applyBrightness(hBar->getValue());
});
10. ToggleButton widget
ToggleButton is a two-state button (checked / unchecked). Query or change the state programmatically, or listen for UIEvent::OnStateChange:
[toggle](const lysa::Event&) {
const bool on = toggle->getState() == lysa::ui::CheckWidget::CHECK;
lysa::Log::info(std::string("Fullscreen: ") + (on ? "ON" : "OFF"));
});
11. TreeView widget
TreeView displays a hierarchical list of widgets with expand/collapse handles and a vertical scroll bar:
const auto rootA = tree->addItem(
std::make_shared<lysa::ui::Text>("Root A"));
const auto rootB = tree->addItem(
std::make_shared<lysa::ui::Text>("Root B"));
const auto childA1 = tree->addItem(rootA,
std::make_shared<lysa::ui::Text>("Child A.1"));
tree->addItem(rootA,
std::make_shared<lysa::ui::Text>("Child A.2"));
tree->expand(rootA->item);
tree->removeAllItems();
12. Applying a style
Every Window uses StyleClassic by default. You can set a custom style or reconfigure the classic style options:
uiWindow->setStyle(nullptr);
style->setOption(
"focus",
"0.3,0.5,0.9,1.0");
style->setOption(
"shadow_dark",
"0.1,0.1,0.1,1.0");
style->setOption(
"shadow_bright",
"0.9,0.9,0.9,1.0");
uiWindow->setStyle(
style);
Widget resource strings are parsed by the active style. For StyleClassic, a resource string can encode the desired size and appearance:
13. Show, hide, and enable
Visibility changes take effect at the start of the next frame. Use show() / hide() as convenient aliases:
statusLabel->show();
debugPanel->show(false);
hud->show();
pauseMenu->hide();
pauseMenu->setVisible(!pauseMenu->isVisible());
Disabling a widget prevents it from responding to mouse and keyboard events but keeps it visible:
submitButton->enable(false);
submitButton->enable(true);
Force an "immediate" repaint of a widget and its children (widgets are drawn at the start of each frame):