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.
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
UIInteractionSystemruns first in a frame (before game logic) and updates every interactable's hovered, held and clicked flags from the input state; a button'sm_OnClickfires when it is released while hovered.UILayoutSystemplaces each panel's children. A panel's layout isAbsolute(children keep their position),Grid(rows and columns),VStackorHStack; a child may carry aUILayoutItemto 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