Skip to main content

MenuNavigationSystem.ixx File

System for handling menu navigation input. More...

Included Headers

Namespaces Index

namespacehelios
namespaceengine

Main engine module aggregating core infrastructure and game systems. More...

namespacemodules

Domain-specific components and systems. More...

namespaceui

User interface components and systems for game entities. More...

namespacewidgets

UI widget components and systems. More...

namespacesystems

UI widget processing systems. More...

Classes Index

classMenuNavigationSystem

Handles gamepad input for menu navigation. More...

Description

System for handling menu navigation input.

File Listing

The file content with the documentation metadata removed is:

1/**
2 * @file MenuNavigationSystem.ixx
3 * @brief System for handling menu navigation input.
4 */
5module;
6
7#include <iostream>
8#include <algorithm>
9#include <cassert>
10
11export module helios.engine.modules.ui.widgets.systems.MenuNavigationSystem;
12import helios.engine.ecs;
13
14import helios.engine.modules.ui.widgets.components.MenuComponent;
15
16import helios.engine.mechanics.lifecycle.components.Active;
17
18import helios.engine.modules.ui.widgets.types;
19import helios.engine.modules.ui.widgets.components.UiFocusComponent;
20import helios.engine.modules.ui.widgets.components.UiStateComponent;
21import helios.engine.modules.ui.widgets.components.UiActionComponent;
22
23import helios.engine.modules.ui.widgets.commands.UiActionCommand;
24
25import helios.engine.runtime.world;
26
27import helios.engine.mechanics.lifecycle.components.Active;
28
29import helios.engine.state.Bindings;
30import helios.engine.runtime.messaging.command.EngineCommandBuffer;
31
32import helios.input.types.Gamepad;
33import helios.input.gamepad.GamepadState;
34
35import helios.engine.ecs.components.HierarchyComponent;
36
37import helios.engine.modules.rendering.model.components.ModelAabbComponent;
38
39using namespace helios::input::types;
42using namespace helios::engine::ecs;
46using namespace helios::input::gamepad;
47
48import helios.engine.common.tags.SystemRole;
49
51
52 /**
53 * @brief Handles gamepad input for menu navigation.
54 *
55 * @details Processes Up/Down input to change selection and A button
56 * to activate the selected menu item. Updates UiStateComponent
57 * selection state and issues UiActionCommand on activation.
58 *
59 * ## Input Handling
60 *
61 * - **Up/Down**: Navigate through menu items
62 * - **A Button**: Activate selected item (triggers UiActionCommand)
63 *
64 * @see MenuComponent
65 * @see MenuDisplaySystem
66 * @see UiActionCommand
67 */
69
70
71 /**
72 * @brief Updates menu selection state.
73 *
74 * @details Moves focus to the new index, updates UiStateComponent
75 * selection flags, and clears the dirty flag.
76 *
77 * @param updateContext The current frame's update context.
78 * @param mc The menu component to update.
79 * @param index The new selected index.
80 * @param gamepadState The current gamepad state.
81 */
82 void updateMenu(helios::engine::runtime::world::UpdateContext& updateContext, MenuComponent* mc, const size_t index) {
83
84 auto menuItems = mc->menuItems();
85
86 const auto prevIndex = mc->previousSelectedIndex();
87
88 if (prevIndex == index && !mc->isDirty()) {
89 return;
90 }
91
92 UiStateComponent* usc = nullptr;
93
94 if (index != prevIndex) {
95 usc = updateContext.find(menuItems[prevIndex])->get<UiStateComponent>();
96 if (usc) {
97 usc->setSelected(false);
98 }
99 }
100 mc->setSelectedIndex(index);
101
102 // update ui state
103 usc = updateContext.find(menuItems[index])->get<UiStateComponent>();
104 if (usc) {
105 usc->setSelected(true);
106 }
107
108 mc->clearDirty();
109 }
110
111
112 public:
113
115
116
117 /**
118 * @brief Processes menu navigation input.
119 *
120 * @details Finds the currently focused menu item, handles Up/Down
121 * navigation, and triggers UiActionCommand when the A button is
122 * pressed on an item with a UiActionComponent.
123 *
124 * @param updateContext The current frame's update context.
125 */
127
128 MenuComponent* focusedMenu = nullptr;
129
130 for (auto [entity, fc, hc, active] : updateContext.view<
132 >().whereEnabled()) {
133 assert(hc->parent() && updateContext.find(*hc->parent()) && updateContext.find(*hc->parent())->get<MenuComponent>() && "Item expected to have parent menu component.");
134 focusedMenu = updateContext.find(*hc->parent())->get<MenuComponent>();
135 break;
136 }
137
138 if (!focusedMenu) {
139 return;
140 }
141
142 const auto size = focusedMenu->menuItems().size();
143
144 const auto& gamepadState = updateContext.inputSnapshot().gamepadState();
145
146 if (gamepadState.isButtonPressed(GamepadInput::Up)) {
147
148 if (focusedMenu->selectedIndex() >= 1) {
149 updateMenu(updateContext, focusedMenu, focusedMenu->selectedIndex() - 1);
150 } else {
151 updateMenu(updateContext, focusedMenu, 0);
152 }
153
154 } else if (gamepadState.isButtonPressed(GamepadInput::Down)) {
155
156 if (focusedMenu->selectedIndex() + 1 < size) {
157 updateMenu(updateContext, focusedMenu, focusedMenu->selectedIndex() + 1);
158 } else {
159 updateMenu(updateContext, focusedMenu, size - 1);
160 }
161
162 } else {
163 updateMenu(updateContext, focusedMenu, focusedMenu->selectedIndex());
164 }
165
166 if (gamepadState.isButtonPressed(GamepadInput::A)) {
167 auto* uac = updateContext.find(focusedMenu->menuItems()[focusedMenu->selectedIndex()])->get<
169 >();
170
171 if (uac) {
173 focusedMenu->menuItems()[focusedMenu->selectedIndex()], uac->actionId()
174 );
175 }
176 }
177 }
178
179
180
181 };
182
183}

Generated via doxygen2docusaurus 2.0.0 by Doxygen 1.15.0.