Build a navigable menu¶
A navigable menu lets the player move focus between items with
directional input, confirm the focused item, and cancel back out
of the menu. The pattern combines BeginNavigation,
NavigationElement, IsFocused, and Button.
For the model behind navigation, refer to Navigation. For the inputs that move focus and trigger confirm and cancel, refer to Input bindings.
To build a navigable menu¶
- Wrap the menu in
BeginNavigation. Passactive: trueand aninitialFocusid so a default element focuses on the first frame: - Lay the items out in the visual order navigation should follow.
PushSeriesVertical(or any layout schema) defines the geometry directional scoring uses to pick the target for each direction: - Register each item with
NavigationElementand draw a focus visual throughIsFocused.ButtonreadsBindings.Navigation.Confirm(), so a focused button activates on the frame the confirm input fires:
The menu is now navigable. Directional input moves focus
between the registered items; confirm activates the focused
item. To handle cancel, read Bindings.Navigation.Cancel() in
the menu body and call PopNavigation — see
Open a submenu.
Open a submenu¶
A submenu becomes its own navigation block. Push it from the outer menu so cancel returns to the parent:
if (MenuItem(ui, "settings", "Settings"))
ui.PushNavigation("settings_menu");
ui.BeginNavigation("settings_menu", initialFocus: "volume");
{
using (ui.Auto().Pad(20).PushSeriesVertical(32, 5))
{
if (MenuItem(ui, "volume", "Volume")) OpenVolume();
ui.Next();
if (MenuItem(ui, "key_binds", "Key binds")) OpenKeyBinds();
}
if (ui.IsNavigationActive("settings_menu") && ui.Bindings.Navigation.Cancel())
ui.PopNavigation();
}
ui.EndNavigation();
BeginNavigation("settings_menu", …) declares the inner block
without activating it. PushNavigation("settings_menu")
activates the block on the next frame and saves the outer block's
focused element. A PushNavigation'd block has no owning element,
so the built-in cancel handler leaves it in place; read
Bindings.Navigation.Cancel() in the submenu body and call
PopNavigation to step back to the outer block, which restores its
previous focus.
IsNavigationFirstFrame("settings_menu") reads true on the
first frame after the push, which is the right hook for
playing an open animation or making a sound.
Combine navigation with the mouse¶
A widget can be both navigable and clickable. Button returns
true on a confirmed-focus press or on a mouse click. The
calling code does not need to know which path triggered it.
Hover state still drives the visual when the mouse is present:
Color tint =
ui.IsHovered() ? hoverColor :
ui.IsFocused(id) ? focusColor :
restColor;
ui.FillRounded(tint, 5);
Mouse hover and navigation focus stay independent. Moving the mouse over an item does not change focus, and moving focus does not warp the cursor.
Pitfalls¶
Direction never moves on the first frame.
: No element holds focus. Pass initialFocus to
BeginNavigation, or call SetFocus(id) manually after the
first frame the block is active.
Two adjacent items skip each other on a directional press.
: The projected direction from the focused element to the
neighbour does not fall inside the 0.5 dot-product cone, or a
third element scores higher. Lay the items closer to a cardinal
direction relative to each other.
Cancel exits the wrong menu.
: The built-in cancel pops only a block entered by confirming an
owning element, returning to that element. For a
PushNavigation'd submenu, the app drives the back step by
reading Bindings.Navigation.Cancel() and calling
PopNavigation. Guard that call so it does not reach the root
block when no submenu is active, or the root pops with nothing
beneath it.
A confirmed button fires at the same time as a mouse click.
: Both paths trigger Button. The widget treats it as a
single activation. To distinguish the source, read
Bindings.Navigation.Confirm() or ui.IsHovered() directly
instead of relying on Button's return value.
Additional resources¶
- Navigation: the model the procedure above applies.
- Configure input bindings: the procedure for changing what triggers confirm, cancel, and the directional moves.
- Make a button: the visual pattern that menu items extend.