Skip to main content

UiTransformSystem.ixx File

System for computing UI element screen positions. 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...

namespacetransform

UI transform components and positioning systems. More...

namespacesystems

UI positioning systems. More...

Classes Index

classUiTransformSystem

Computes screen positions for UI elements based on layout configuration. More...

Description

System for computing UI element screen positions.

File Listing

The file content with the documentation metadata removed is:

1/**
2 * @file UiTransformSystem.ixx
3 * @brief System for computing UI element screen positions.
4 */
5module;
6
7#include <cassert>
8#include <utility>
9
10export module helios.engine.modules.ui.transform.systems.UiTransformSystem;
11
12
13
14import helios.engine.modules.ui.transform.components.UiTransformComponent;
15import helios.engine.modules.spatial.transform.components.TranslationStateComponent;
16import helios.engine.modules.spatial.transform.components.ComposeTransformComponent;
17import helios.engine.modules.ui.layout.Anchor;
18
19import helios.engine.runtime.world.UpdateContext;
20import helios.engine.runtime.world.GameWorld;
21
22import helios.engine.modules.scene.components.SceneNodeComponent;
23
24import helios.engine.modules.rendering.model.components.ModelAabbComponent;
25
26import helios.engine.mechanics.lifecycle.components.Active;
27
28import helios.math;
29
30import helios.engine.ecs.components.HierarchyComponent;
31
32import helios.engine.common.tags.SystemRole;
33
35
36
37 /**
38 * @brief Computes screen positions for UI elements based on layout configuration.
39 *
40 * @details This system processes entities with UiTransformComponent and computes
41 * their final screen positions. The positioning algorithm considers:
42 *
43 * - **Anchor:** Where the element attaches to its parent (Center, TopLeft, etc.)
44 * - **Pivot:** The element's own reference point for positioning
45 * - **Offsets:** Margins from the anchor point (top, right, bottom, left)
46 * - **Viewport:** Current viewport dimensions for root-level elements
47 * - **Parent bounds:** For nested UI elements via HierarchyComponent
48 *
49 * ## Hierarchy Support
50 *
51 * For elements with a HierarchyComponent, the system uses the parent entity's
52 * AABB and transform to compute relative positioning. Root elements (those
53 * attached to the scene root) use viewport dimensions as their parent bounds.
54 *
55 * ## Required Components
56 *
57 * | Component | Purpose |
58 * |-----------|---------|
59 * | `UiTransformComponent` | Layout configuration (anchor, pivot, offsets) |
60 * | `TranslationStateComponent` | Receives computed position |
61 * | `ComposeTransformComponent` | Transform composition |
62 * | `ModelAabbComponent` | Element bounds for size calculations |
63 * | `SceneNodeComponent` | Scene graph integration |
64 * | `Active` | Lifecycle tag |
65 *
66 * @see UiTransformComponent
67 * @see Anchor
68 * @see HierarchyComponent
69 */
71
72 /**
73 * @brief Adjusts position based on pivot point and element size.
74 *
75 * @details Transforms a position from anchor-relative to pivot-relative
76 * coordinates. The pivot determines which point of the element is placed
77 * at the anchor position.
78 *
79 * @param unanchored The position before pivot adjustment.
80 * @param size The size of the element.
81 * @param pivot The pivot point to apply.
82 *
83 * @return The adjusted position accounting for pivot offset.
84 */
86 const helios::math::vec3f unanchored,
89
90 switch (pivot) {
91
93 return unanchored - size * 0.5f;
94
96 return unanchored - size;
97
99 return unanchored.withY(unanchored[1] - size[1]);
100
102 return unanchored;
103 }
104
105 assert(false && "Unreachable!");
106 std::unreachable();
107 }
108
109 public:
110
112
113
114 /**
115 * @brief Computes and applies screen positions for all UI elements.
116 *
117 * @details Iterates over all entities with UI layout components and computes
118 * their final screen positions. For each entity:
119 *
120 * 1 Finds the matching viewport snapshot by viewportId
121 * 2 Determines parent bounds (viewport for root, parent AABB otherwise)
122 * 3 Computes anchor position based on anchor type and offsets
123 * 4 Adjusts for pivot point
124 * 5 Updates TranslationStateComponent with final position
125 *
126 * @param updateContext The current frame's update context.
127 */
129
130 for (auto [entity, tc, tsc, ctc, mbc, snc, active] : updateContext.view<
137 >().whereEnabled()) {
138
139 if (!tc->viewportId()) {
140 continue;
141 }
142
143 for (const auto& snapshot : updateContext.viewportSnapshots()) {
144 if (snapshot.viewportId != tc->viewportId()) {
145 continue;
146 }
147
148 auto pivot = tc->pivot();
149
150 auto sceneNode = snc->sceneNode();
151
152 float viewportWidth;
153 float viewportHeight;
154
155 auto uiRect = helios::math::vec4f(
156 mbc->aabb().min()[0], mbc->aabb().min()[1],
157 mbc->aabb().size()[0], mbc->aabb().size()[1]
158 );
159 auto worldRect = helios::math::vec4f(
160 uiRect[0] + uiRect[0] / 2.0f,
161 uiRect[1] + uiRect[1] / 2.0f,
162 uiRect[2], uiRect[3]
163 );
164
165
166 auto parentUiRect = helios::math::vec4f{};
167 auto parentWorldRect = helios::math::vec4f{};
168
169 const auto offsets = tc->offsets();
170
171 if (sceneNode->parent()->isRoot()) {
172 viewportWidth = snapshot.absoluteBounds[2];
173 viewportHeight = snapshot.absoluteBounds[3];
174
175 parentUiRect = helios::math::vec4f(0, 0, viewportWidth, viewportHeight);
176
177 parentWorldRect = helios::math::vec4f(
178 viewportWidth / 2.0f,
179 viewportHeight /2.0f,
180 viewportWidth,
181 viewportHeight
182 );
183
184 } else {
185
187
188 if (!hc || !hc->parent()) {
189 continue;
190 }
191
192 // we rely on the parent entity so we do not have to wait for the SceneGraph sync
193 if (auto parentGo = updateContext.find(hc->parent().value())) {
194 auto* pmaabbcc = parentGo->get<rendering::model::components::ModelAabbComponent>();
196
197 auto size = pmaabbcc->aabb().size() * pctc->localScaling();
198
199 parentUiRect = helios::math::vec4f(
200 -(size[0] * 0.5f),
201 -(size[1] * 0.5f),
202 size[0],
203 size[1]
204 );
205 }
206 }
207
208
209 switch (tc->anchor()) {
210
212 auto anchored = helios::math::vec3f(
213 parentUiRect[0] + parentUiRect[2]/2.0f - offsets[1] ,
214 parentUiRect[1] + parentUiRect[3]/2.0f - offsets[0], 0.0f
215 );
216 anchored = anchor(anchored, mbc->aabb().size(), pivot);
217 tsc->setTranslation(anchored);
218 }
219 break;
220
222 auto anchored = helios::math::vec3f(
223 parentUiRect[0] + parentUiRect[2] - offsets[1],
224 parentUiRect[1] + parentUiRect[3] - offsets[0],
225 0.0f
226 );
227 anchored = anchor(anchored, mbc->aabb().size(), pivot);
228 tsc->setTranslation(anchored);
229 }
230 break;
231
233 auto anchored = helios::math::vec3f(
234 parentUiRect[0] + offsets[3],
235 parentUiRect[1] + parentUiRect[3] - offsets[0],
236 0.0f
237 );
238 anchored = anchor(anchored, mbc->aabb().size(), pivot);
239 tsc->setTranslation(anchored);
240 }
241 break;
242
244 auto anchored = helios::math::vec3f(
245 parentUiRect[0] + offsets[3],
246 parentUiRect[1] + offsets[2],
247 0.0f
248 );
249 anchored = anchor(anchored, mbc->aabb().size(), pivot);
250 tsc->setTranslation(anchored);
251 }
252 break;
253
254 }
255 }
256 }
257 }
258 };
259}
260
261

Generated via doxygen2docusaurus 2.0.0 by Doxygen 1.15.0.