1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
//! [`NavMenu`] builders to convert into [`TreeMenu`].
//!
//! This module defines a bunch of "seed" bundles. Systems in [`crate::named`],
//! [`crate::marker`] and [`crate::resolve`] will take the components
//! defined in those seeds and replace them by [`NavMenu`]s. It is necessary
//! for a few things:
//! * The [`active_child`](TreeMenu::active_child) field of `NavMenu`, which
//! cannot be inferred without the [`Focusable`](crate::Focusable)s children of that menu
//! * Finding the [`Focusable`](crate::Focusable) specified in [`ParentName`]
//!
//! # Seed bundles
//!
//! Seed bundles are collections of components that will trigger various
//! pre-processing to create a [`TreeMenu`]. They are a combination of those
//! components:
//! * [`TreeMenuSeed`]: the base seed, which will be converted into a [`TreeMenu`]
//! in [`crate::resolve::insert_tree_menus`].
//! * [`ParentName`], the *by-name* marker: marks a [`TreeMenuSeed`] as needing
//! its [`focus_parent`](TreeMenuSeed::focus_parent) to be updated by
//! [`crate::named::resolve_named_menus`] with the [`Focusable`](crate::Focusable) which
//! [`Name`](https://docs.rs/bevy/0.9.0/bevy/core/struct.Name.html) matches
//! the one in [`ParentName`]. If for whatever reason that update doesn't
//! happen, [`crate::resolve::insert_tree_menus`] will panic.
//! * [`NavMarker<T>`], the *automarking* marker: marks a [`NavMenu`] as
//! inserting a `T` component to all it's enclosed [`Focusable`](crate::Focusable)s. The
//! [`NavMarker<T>`] will then be used by
//! [`NavMarkerPropagationPlugin<T>`](crate::NavMarkerPropagationPlugin) to
//! automatically add the marker to the children [`Focusable`](crate::Focusable)s.
//!
//! Those components are combined in the seed bundles. Which processing step is
//! applied to the [`TreeMenuSeed`] depends on which components it was inserted
//! with. The bundles are:
//! * [`MenuSeed`]: Creates a [`NavMenu`].
//! * [`NamedMenuSeed`]: Creates a [`NavMenu`] "reachable from" the
//! [`Focusable`](crate::Focusable) named in the [`ParentName`].
//! * [`MarkingMenuSeed`]: Creates a [`NavMenu`] that will insert the
//! marker component specified in [`NavMarker<T>`] in all it's [`Focusable`](crate::Focusable)
//! children.
//! * [`NamedMarkingMenuSeed`]: Combination of [`NamedMenuSeed`] and
//! [`MarkingMenuSeed`].
//!
//! # Ordering
//!
//! In order to correctly create the [`TreeMenu`] specified with the bundles
//! declared int this module, the systems need to be ran in this order:
//!
//! ```text
//! named::resolve_named_menus → resolve::insert_tree_menus → marker::mark_new_menus
//! ```
//! The insert/mark relationship is not necessary, it will eventually correctly
//! mark focusables. However, if you want to avoid a 1 frame latency on marking
//! entities with the specified component, you need to have a stage boundary
//! between `insert_tree_menus` and `mark_new_menus`.
//!
//! The resolve_named/insert relationship should be upheld. Otherwise, root
//! NavMenus will spawn instead of NavMenus with parent with given name.
use Cow;
use *;
use crateTreeMenu;
/// Option of an option.
///
/// It's really just `Option<Option<T>>` with some semantic sparkled on top.
pub
/// An uninitialized [`TreeMenu`].
///
/// It is added through one of the bundles defined in this crate by the user,
/// and picked up by the [`crate::resolve::insert_tree_menus`] system to create the
/// actual [`TreeMenu`] handled by the resolution algorithm.
pub
/// Component to specify creation of a [`TreeMenu`] refering to their parent
/// focusable by [`Name`](https://docs.rs/bevy/0.9.0/bevy/core/struct.Name.html)
///
/// It is used in [`crate::named::resolve_named_menus`] to figure out the
/// `Entity` id of the named parent of the [`TreeMenuSeed`] and set its
/// `focus_parent` field.
pub Name);
/// Component to add to [`NavMenu`] entities to propagate `T` to all
/// [`Focusable`](crate::Focusable) children of that menu.
pub T);
/// A menu that isolate children [`Focusable`](crate::Focusable)s from other
/// focusables and specify navigation method within itself.
///
/// # Usage
///
/// A [`NavMenu`] can be used to:
/// * Prevent navigation from one specific submenu to another
/// * Specify if 2d navigation wraps around the screen, see
/// [`NavMenu::Wrapping2d`].
/// * Specify "scope menus" such that a
/// [`NavRequest::ScopeMove`](crate::NavRequest::ScopeMove) emitted when
/// the focused element is a [`Focusable`](crate::Focusable) nested within this `NavMenu`
/// will navigate this menu. See [`NavMenu::BoundScope`] and
/// [`NavMenu::WrappingScope`].
/// * Specify _submenus_ and specify from where those submenus are reachable.
/// * Add a specific component to all [`Focusable`](crate::Focusable)s in this menu. You must
/// first create a "seed" bundle with any of the [`NavMenu`] methods and then
/// call [`marking`](MenuSeed::marking) on it.
/// * Specify which entity will be the parents of this [`NavMenu`], see
/// [`NavMenu::reachable_from`] or [`NavMenu::reachable_from_named`] if you don't
/// have access to the [`Entity`](https://docs.rs/bevy/0.9.0/bevy/ecs/entity/struct.Entity.html)
/// for the parent [`Focusable`](crate::Focusable)
///
/// If you want to specify which [`Focusable`](crate::Focusable) should be
/// focused first when entering a menu, you should mark one of the children of
/// this menu with [`Focusable::dormant`](crate::Focusable::dormant).
///
/// ## Example
///
/// See the example in this [crate]'s root level documentation page.
///
/// # Invariants
///
/// **You need to follow those rules (invariants) to avoid panics**:
/// 1. A `Menu` must have **at least one** [`Focusable`](crate::Focusable) child in the UI
/// hierarchy.
/// 2. There must not be a menu loop. Ie: a way to go from menu A to menu B and
/// then from menu B to menu A while never going back.
/// 3. Focusables in 2d menus must have a `GlobalTransform`.
///
/// # Panics
///
/// Thankfully, programming errors are caught early and you'll probably get a
/// panic fairly quickly if you don't follow the invariants.
/// * Invariant (1) panics as soon as you add the menu without focusable
/// children.
/// * Invariant (2) panics if the focus goes into a menu loop.
/// A "seed" for creation of a [`NavMenu`].
///
/// Internally, `bevy_ui_navigation` uses a special component to mark UI nodes
/// as "menus", this tells the navigation algorithm to add that component to
/// this `Entity`.
/// Bundle to specify creation of a [`NavMenu`] refering to their parent
/// focusable by [`Name`](https://docs.rs/bevy/0.9.0/bevy/core/struct.Name.html)
///
/// This is useful if, for example, you just want to spawn your UI without
/// keeping track of entity ids of buttons that leads to submenus.
/// A [`NavMenu`] with automatic `T` marker propagation
///
/// A `NavMenu` created from this bundle will automatically mark all
/// [`Focusable`](crate::Focusable)s within that menu with the `T` component.
///
/// In order for `T` to propagate to the children of this menu, you need to add
/// the [`NavMarkerPropagationPlugin<T>`](crate::NavMarkerPropagationPlugin) to
/// your bevy app.
/// This is a combination of [`MarkingMenuSeed`] and [`NamedMenuSeed`], see the
/// documentation of those items for details.