载入中...
搜索中...
未找到
UIHost.cpp
浏览该文件的文档.
1#include "ui/UIHost.h"
2#include "ui/Widget.h"
3
4#include <algorithm>
5
6namespace eve::ui {
7namespace {
8
9uint32_t g_anonHostSeq = 0;
10
11bool focusableType(NodeType type) {
12 switch (type) {
18 case NodeType::Combo:
23 case NodeType::MenuItem: return true;
24 default: return false;
25 }
26}
27
28bool eligible(const UINode &node, bool sequential) {
29 return focusableType(node.type) && !node.id.empty() && node.visible && node.enabled &&
30 (sequential ? node.focusMode == FocusMode::All
31 : node.focusMode != FocusMode::None);
32}
33
34const std::string &neighbor(const UINode &node, FocusDirection direction) {
35 switch (direction) {
36 case FocusDirection::Next: return node.focusNext;
37 case FocusDirection::Previous: return node.focusPrevious;
38 case FocusDirection::Left: return node.focusLeft;
39 case FocusDirection::Right: return node.focusRight;
40 case FocusDirection::Up: return node.focusUp;
41 case FocusDirection::Down: return node.focusDown;
42 }
43 return node.focusNext;
44}
45
46} // namespace
47
49 UIHost *h = UIHost::create();
50 if (!h) return {};
51 const UIHostHandle handle = ecs::handle_of(h);
52 h->meta()->entity = handle;
53 if (name.empty()) {
54 h->meta()->name = "host" + std::to_string(++g_anonHostSeq);
55 } else {
56 h->meta()->name = name;
57 }
58 return handle;
59}
60
62 auto *entity = ecs::try_get(handle);
63 if (auto *host = entity ? dynamic_cast<UIHost *>(entity) : nullptr) return std::ref(*host);
64 return std::nullopt;
65}
66
67void UIHost::setName(const std::string &name) { meta()->name = name; }
68
69const std::string &UIHost::getName() { return meta()->name; }
70
72 meta()->hasThemeOverride = true;
73 meta()->themeOverride = theme;
74}
75
76void UIHost::clearThemeOverride() { meta()->hasThemeOverride = false; }
77
78bool UIHost::hasThemeOverride() { return meta()->hasThemeOverride; }
79
81 return meta()->hasThemeOverride ? &meta()->themeOverride : nullptr;
82}
83
84void UIHost::setWorldAnchor(float x, float y, float z) {
85 auto anchor = worldAnchor();
86 anchor->enabled = true;
87 anchor->worldX = x;
88 anchor->worldY = y;
89 anchor->worldZ = z;
90}
91
93 auto anchor = worldAnchor();
94 anchor->enabled = false;
96 anchor->scale = 1.f;
97}
98
99void UIHost::setTree(WidgetDesc root) { applyTree(this, std::move(root)); }
100
102
103void UIHost::setSimplePanel(const std::string &title, const std::string &labelText,
104 const std::string &buttonText, const std::string &labelId,
105 const std::string &buttonId) {
107 {
108 text(labelText, labelId),
109 button(buttonText, buttonId),
110 },
111 "root"));
112}
113
115 if (id.empty()) return std::nullopt;
116 auto t = tree();
117 for (auto &n : t->nodes) {
118 if (n.id == id) return std::ref(n);
119 }
120 return std::nullopt;
121}
122
124 if (key.empty()) return std::nullopt;
125 auto t = tree();
126 for (auto &n : t->nodes) {
127 if (n.key == key) return std::ref(n);
128 }
129 return std::nullopt;
130}
131
132void UIHost::setTextById(const std::string &id, const std::string &text) {
133 if (auto n = findById(id)) n->get().text = text;
134}
135
136void UIHost::setVisibleById(const std::string &id, bool visible) {
137 if (auto n = findById(id)) n->get().visible = visible;
138}
139
140void UIHost::setEnabledById(const std::string &id, bool enabled) {
141 if (auto n = findById(id)) {
142 n->get().enabled = enabled;
143 if (!enabled) {
144 n->get().focusRequested = false;
145 n->get().focused = false;
146 }
147 }
148}
149
150void UIHost::setCheckedById(const std::string &id, bool checked) {
151 if (auto n = findById(id)) n->get().checked = checked;
152}
153
154void UIHost::setValueById(const std::string &id, float value) {
155 if (auto n = findById(id)) n->get().value = value;
156}
157
158void UIHost::setValueTextById(const std::string &id, const std::string &value) {
159 if (auto n = findById(id)) n->get().valueText = value;
160}
161
162bool UIHost::requestFocusById(const std::string &id) {
163 auto target = findById(id);
164 if (!target || !eligible(target->get(), false)) return false;
165 auto t = tree();
166 for (auto &node : t->nodes) node.focusRequested = false;
167 target->get().focusRequested = true;
168 return true;
169}
170
172 auto t = tree();
173
174 UINode *current = nullptr;
175 for (UINode &node : t->nodes) {
176 if (node.focused) {
177 current = &node;
178 break;
179 }
180 if (!current && node.focusRequested) current = &node;
181 }
182
183 if (current) {
184 const std::string &explicitId = neighbor(*current, direction);
185 if (!explicitId.empty()) {
186 auto explicitTarget = findById(explicitId);
187 if (explicitTarget && eligible(explicitTarget->get(), true)) return requestFocusById(explicitId);
188 }
189 }
190
191 std::vector<std::pair<int, std::size_t>> order;
192 order.reserve(t->nodes.size());
193 for (std::size_t index = 0; index < t->nodes.size(); ++index) {
194 const UINode &node = t->nodes[index];
195 if (eligible(node, true) && node.tabIndex >= 0)
196 order.emplace_back(node.tabIndex, index);
197 }
198 if (order.empty()) return false;
199 std::stable_sort(order.begin(), order.end());
200
201 const bool backwards = direction == FocusDirection::Previous ||
204 std::size_t targetOrder = backwards ? order.size() - 1 : 0;
205 if (current) {
206 const auto found = std::find_if(order.begin(), order.end(),
207 [current, &t](const auto &entry) {
208 return &t->nodes[entry.second] == current;
209 });
210 if (found != order.end()) {
211 const std::size_t position = static_cast<std::size_t>(found - order.begin());
212 if (backwards) {
213 if (position == 0 && !wrap) return false;
214 targetOrder = position == 0 ? order.size() - 1 : position - 1;
215 } else {
216 if (position + 1 == order.size() && !wrap) return false;
217 targetOrder = position + 1 == order.size() ? 0 : position + 1;
218 }
219 }
220 }
221 return requestFocusById(t->nodes[order[targetOrder].second].id);
222}
223
224std::string UIHost::focusedId() {
225 auto t = tree();
226 for (const auto &node : t->nodes) {
227 if (node.focused) return node.id;
228 }
229 return {};
230}
231
232bool UIHost::setClickHandler(const std::string &id, std::function<void()> fn) {
233 auto n = findById(id);
234 if (!n) return false;
235 auto t = tree();
236 if (n->get().handlerClick != 0) {
237 size_t idx = size_t(n->get().handlerClick - 1);
238 if (idx < t->clickHandlers.size()) {
239 t->clickHandlers[idx] = std::move(fn);
240 return true;
241 }
242 }
243 t->clickHandlers.push_back(std::move(fn));
244 n->get().handlerClick = static_cast<uint32_t>(t->clickHandlers.size());
245 return true;
246}
247
248bool UIHost::setToggleHandler(const std::string &id, std::function<void(bool)> fn) {
249 auto n = findById(id);
250 if (!n) return false;
251 auto t = tree();
252 if (n->get().handlerToggle != 0) {
253 size_t idx = size_t(n->get().handlerToggle - 1);
254 if (idx < t->toggleHandlers.size()) {
255 t->toggleHandlers[idx] = std::move(fn);
256 return true;
257 }
258 }
259 t->toggleHandlers.push_back(std::move(fn));
260 n->get().handlerToggle = static_cast<uint32_t>(t->toggleHandlers.size());
261 return true;
262}
263
264bool UIHost::setValueHandler(const std::string &id, std::function<void(float)> fn) {
265 auto n = findById(id);
266 if (!n) return false;
267 auto t = tree();
268 if (n->get().handlerValue != 0) {
269 size_t idx = size_t(n->get().handlerValue - 1);
270 if (idx < t->valueHandlers.size()) {
271 t->valueHandlers[idx] = std::move(fn);
272 return true;
273 }
274 }
275 t->valueHandlers.push_back(std::move(fn));
276 n->get().handlerValue = static_cast<uint32_t>(t->valueHandlers.size());
277 return true;
278}
279
280bool UIHost::setTextHandler(const std::string &id, std::function<void(const std::string &)> fn) {
281 auto n = findById(id);
282 if (!n) return false;
283 auto t = tree();
284 if (n->get().handlerText != 0) {
285 size_t idx = size_t(n->get().handlerText - 1);
286 if (idx < t->textHandlers.size()) {
287 t->textHandlers[idx] = std::move(fn);
288 return true;
289 }
290 }
291 t->textHandlers.push_back(std::move(fn));
292 n->get().handlerText = static_cast<uint32_t>(t->textHandlers.size());
293 return true;
294}
295
296} // namespace eve::ui
LogicalId target
double value
float y
Definition AnimClip.cpp:738
float x
Definition AnimClip.cpp:738
float z
Definition AnimClip.cpp:738
int root
Definition AnimSmr.cpp:119
Vec3 anchor
Definition CaveMesh.cpp:90
std::string title
Object::Ptr theme
std::uint32_t key
glm::vec3 n
Definition Grass.cpp:63
int h
std::string text
std::array< float, 3 > position
std::string name
std::vector< std::int32_t > order
int idx
PrimitiveHandle handle
float t
const RoadNode * node
RoadLaneDirection direction
bool found
double current
bool visible
UIHostHandle host
uint32_t index
ECS mount point for one UI panel/screen. Subclass to attach UI to game entities, e....
Definition UIHost.h:243
bool setTreeReconcile(WidgetDesc root)
Key-aware patch when structure matches; else full replace.
Definition UIHost.cpp:101
void setTree(WidgetDesc root)
Full replace.
Definition UIHost.cpp:99
void setCheckedById(const std::string &id, bool checked)
Definition UIHost.cpp:150
eve::OptionalRef< UINode > findById(const std::string &id)
Looks up a node by stable id without transferring ownership.
Definition UIHost.cpp:114
std::string focusedId()
Return the currently focused control id, or an empty string.
Definition UIHost.cpp:224
void setValueById(const std::string &id, float value)
Definition UIHost.cpp:154
bool setToggleHandler(const std::string &id, std::function< void(bool)> fn)
Definition UIHost.cpp:248
const std::string & getName()
Definition UIHost.cpp:69
void setThemeOverride(const Theme &theme)
Apply a host-local Theme without mutating ui::globalTheme().
Definition UIHost.cpp:71
const Theme * themeOverride()
Borrow the host-local Theme when one is installed.
Definition UIHost.cpp:80
void clearThemeOverride()
Stop using a host-local Theme and inherit the process global again.
Definition UIHost.cpp:76
bool moveFocus(FocusDirection direction, bool wrap=true)
Move through explicit neighbors or deterministic tab order.
Definition UIHost.cpp:171
bool setTextHandler(const std::string &id, std::function< void(const std::string &)> fn)
Definition UIHost.cpp:280
void setName(const std::string &name)
Names the host.
Definition UIHost.cpp:67
bool hasThemeOverride()
True when a host-local Theme is installed.
Definition UIHost.cpp:78
bool setClickHandler(const std::string &id, std::function< void()> fn)
Installs a widget callback by node id (returns false if not found).
Definition UIHost.cpp:232
static UIHostHandle createHost(const std::string &name="")
Creates an ECS-owned UI host.
Definition UIHost.cpp:48
void setVisibleById(const std::string &id, bool visible)
Definition UIHost.cpp:136
UIHostHandle handle() const noexcept
Returns this host's generation-qualified ECS handle.
Definition UIHost.h:364
void setValueTextById(const std::string &id, const std::string &value)
Definition UIHost.cpp:158
void clearWorldAnchor()
Disables 3D projection and returns the host to normal screen layout.
Definition UIHost.cpp:92
void setTextById(const std::string &id, const std::string &text)
Widget state updates by node id.
Definition UIHost.cpp:132
void setWorldAnchor(float x, float y, float z)
Enables projection of this host from a 3D world point.
Definition UIHost.cpp:84
void setEnabledById(const std::string &id, bool enabled)
Definition UIHost.cpp:140
void setSimplePanel(const std::string &title, const std::string &labelText, const std::string &buttonText, const std::string &labelId="label", const std::string &buttonId="btn")
One-shot convenience panel: window + label + button.
Definition UIHost.cpp:103
static eve::OptionalRef< UIHost > resolve(UIHostHandle handle) noexcept
Resolves a UI host handle with ECS generation checking.
Definition UIHost.cpp:61
bool setValueHandler(const std::string &id, std::function< void(float)> fn)
Definition UIHost.cpp:264
eve::OptionalRef< UINode > findByKey(const std::string &key)
Looks up a node by reconciliation key without transferring ownership.
Definition UIHost.cpp:123
bool requestFocusById(const std::string &id)
Request keyboard/gamepad focus for a control on the next frame.
Definition UIHost.cpp:162
void applyTree(UIHost *host, WidgetDesc root)
Full replace flatten.
Definition Widget.cpp:735
WidgetDesc window(std::string title, std::vector< WidgetDesc > children, std::string id)
Top-level window widget with a title bar.
Definition Widget.cpp:292
NodeType
Widget node kinds understood by the UI renderer.
Definition UIHost.h:19
FocusDirection
Logical focus movement understood by keyboard, gamepad and automation.
Definition UIHost.h:82
WidgetDesc button(std::string label, std::string id, std::function< void()> onClick)
Clickable button; fires onClick.
Definition Widget.cpp:311
ecs::EntityHandle UIHostHandle
Definition UIHost.h:16
bool applyTreeReconcile(UIHost *host, WidgetDesc root)
Patch by key/id when structure (type + child keys) matches; otherwise full replace....
Definition Widget.cpp:748
std::optional< std::reference_wrapper< T > > OptionalRef
Optional borrowed reference; it does not extend T's lifetime.
Definition BorrowedRef.h:24
SettlementPipeline::Stage fn
bool enabled
Unified UI design tokens (colors, geometry, typography). Applied to ImGui each frame via applyThemeTo...
Definition Theme.h:39
Retained UI widget node (arena tree). Conceptual counterpart of eve::scene::SceneNode; built declarat...
Definition UIHost.h:128
Declarative widget description (build once / on dirty → flatten into UIHost::Tree).
Definition Widget.h:15