Start

Theory

Reference

Examples

UI

Menus and HUDs in ASGE are ordinary entities with UI components, laid out and clicked by two systems.

The concept

Game UI has two jobs besides drawing: interaction (is the pointer over this, was it clicked) and layout (where does each widget go, so you do not position everything by hand). Treating widgets as entities means the same scene format, hierarchy and editor tooling cover UI too.

Immediate versus retained UI

In immediate-mode UI, code describes the interface every frame (if (Button("Play")) ...) and nothing persists. In retained-mode UI, widgets are objects that exist between frames, hold their own state (hovered, pressed, value) and can be saved. Game menus and HUDs, which are designed by people and loaded from files, fit retained mode.

Hit testing and input states

A button needs more than "mouse is over it". It has states: hovered, held and clicked. A click is conventionally registered when the button is released while still over the widget, so the player can cancel by dragging away. Overlapping widgets need a rule for which one receives the click.

Layout

Positioning every widget by pixel breaks when the window size or text changes. Layout containers place their children: a stack lines them up in a row or column, a grid arranges rows and columns, and absolute layout leaves positions alone. Children can ask to fill the available space or align to an edge. HUD elements are usually anchored to the screen rather than the world, so they stay put when the camera moves.

How ASGE does it

Widgets

Each widget is a bundle of components over a UIRect: UIButton, UILabel, UICheckbox, UISlider and UIPanel. You do not assemble these by hand; the asge::game::ui::Create* functions take a descriptor and return a Result<ecs::Entity>: CreateLabel, CreateButton, CreateCheckbox, CreateSlider and CreatePanel. The editor uses the same functions, so what it builds is what a game gets.

ui.cpp
asge::game::ui::ButtonDesc desc;
desc.m_Name     = "Play";
desc.m_Position = asge::math::Float2{ 16.0f, 16.0f };
desc.m_OnClick  = [] { /* start the game */ };

auto button = asge::game::ui::CreateButton( registry, desc );   // Result<ecs::Entity>

Interaction and layout

  • UIInteractionSystem runs first in a frame (before game logic) and updates every interactable's hovered, held and clicked flags from the input state; a button's m_OnClick fires when it is released while hovered.
  • UILayoutSystem places each panel's children. A panel's layout is Absolute (children keep their position), Grid (rows and columns), VStack or HStack; a child may carry a UILayoutItem to choose whether it fills its slot and how it aligns.
  • Widgets are children of panels through the normal entity Hierarchy; a screen-space flag keeps HUD elements fixed while the camera moves.

Text uses a baked Font loaded through the asset manager; a label with text but no font path is rejected with UIWidgetError::TextWithNoFont.

See also

Source: Game/UI.hpp, Game/Systems/UISystem.hpp, Game/Components/UI/UIPanel.hpp. Arrange the UI in the editor