bevy_ui_navigation/components.rs
1//! Focusable components and bundles to ease navigable UI declaration.
2use bevy::prelude::{Bundle, ButtonBundle, Component, NodeBundle};
3
4use crate::{
5 menu::{MenuBuilder, MenuSetting, NavMarker},
6 resolve::Focusable,
7};
8
9/// A button like the default bevy [`ButtonBundle`], but with an added
10/// [`Focusable`] component so that it can be used with this crate.
11#[derive(Default, Clone, Bundle)]
12pub struct FocusableButtonBundle {
13 /// The bevy components.
14 pub button_bundle: ButtonBundle,
15 /// The [`Focusable`] type.
16 pub focus: Focusable,
17}
18impl From<ButtonBundle> for FocusableButtonBundle {
19 fn from(button_bundle: ButtonBundle) -> Self {
20 FocusableButtonBundle {
21 button_bundle,
22 ..Default::default()
23 }
24 }
25}
26
27/// A [`NodeBundle`] delimiting a menu,
28/// which [`Focusable`] will be marked with `marker`.
29///
30/// - See [`MenuSetting`] for details on how menus work.
31/// - See [`NavMarker`] for how marking works.
32#[derive(Bundle)]
33pub struct MarkingMenuBundle<T: Component> {
34 /// How navigation within that menu works.
35 pub setting: MenuSetting,
36 /// Specify from where this menu is reachable.
37 pub builder: MenuBuilder,
38 /// What component of type `T` to add to all [`Focusable`]s within
39 /// this menu.
40 pub marker: NavMarker<T>,
41 /// The bevy components.
42 pub node: NodeBundle,
43}
44/// A [`NodeBundle`] delimiting a menu.
45///
46/// - See [`MenuSetting`] for details on how menus work.
47/// - Use [`MenuBundle::marking`] if you need [`Focusable`]s in your menu to
48/// share a specific component.
49#[derive(Clone, Bundle)]
50pub struct MenuBundle {
51 /// How navigation within that menu works.
52 pub setting: MenuSetting,
53 /// Specify from where this menu is reachable.
54 pub builder: MenuBuilder,
55 /// The bevy components.
56 pub node: NodeBundle,
57}
58impl MenuBundle {
59 /// Add `marker` to all [`Focusable`]s in this menu whenever it is created.
60 ///
61 /// See [`NavMarker`] for how marking works.
62 pub fn marking<T: Component>(self, marker: T) -> MarkingMenuBundle<T> {
63 let Self {
64 setting,
65 builder,
66 node,
67 } = self;
68 MarkingMenuBundle {
69 setting,
70 builder,
71 marker: NavMarker(marker),
72 node,
73 }
74 }
75}