Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bevyengine
GitHub Repository: bevyengine/bevy
Path: blob/main/examples/ui/tab_navigation.rs
6595 views
1
//! This example illustrates the use of tab navigation.
2
3
use bevy::{
4
color::palettes::basic::*,
5
input_focus::{
6
tab_navigation::{TabGroup, TabIndex, TabNavigationPlugin},
7
InputDispatchPlugin, InputFocus,
8
},
9
prelude::*,
10
};
11
12
fn main() {
13
App::new()
14
.add_plugins((DefaultPlugins, InputDispatchPlugin, TabNavigationPlugin))
15
.add_systems(Startup, setup)
16
.add_systems(Update, (button_system, focus_system))
17
.run();
18
}
19
20
const NORMAL_BUTTON: Color = Color::srgb(0.15, 0.15, 0.15);
21
const HOVERED_BUTTON: Color = Color::srgb(0.25, 0.25, 0.25);
22
const PRESSED_BUTTON: Color = Color::srgb(0.35, 0.75, 0.35);
23
24
fn button_system(
25
mut interaction_query: Query<
26
(&Interaction, &mut BackgroundColor, &mut BorderColor),
27
(Changed<Interaction>, With<Button>),
28
>,
29
) {
30
for (interaction, mut color, mut border_color) in &mut interaction_query {
31
match *interaction {
32
Interaction::Pressed => {
33
*color = PRESSED_BUTTON.into();
34
*border_color = BorderColor::all(RED);
35
}
36
Interaction::Hovered => {
37
*color = HOVERED_BUTTON.into();
38
*border_color = BorderColor::all(Color::WHITE);
39
}
40
Interaction::None => {
41
*color = NORMAL_BUTTON.into();
42
*border_color = BorderColor::all(Color::BLACK);
43
}
44
}
45
}
46
}
47
48
fn focus_system(
49
mut commands: Commands,
50
focus: Res<InputFocus>,
51
mut query: Query<Entity, With<Button>>,
52
) {
53
if focus.is_changed() {
54
for button in query.iter_mut() {
55
if focus.0 == Some(button) {
56
commands.entity(button).insert(Outline {
57
color: Color::WHITE,
58
width: px(2),
59
offset: px(2),
60
});
61
} else {
62
commands.entity(button).remove::<Outline>();
63
}
64
}
65
}
66
}
67
68
fn setup(mut commands: Commands) {
69
// ui camera
70
commands.spawn(Camera2d);
71
commands
72
.spawn(Node {
73
width: percent(100),
74
height: percent(100),
75
display: Display::Flex,
76
flex_direction: FlexDirection::Column,
77
align_items: AlignItems::Center,
78
justify_content: JustifyContent::Center,
79
row_gap: px(6),
80
..default()
81
})
82
.observe(
83
|mut event: On<Pointer<Click>>, mut focus: ResMut<InputFocus>| {
84
focus.0 = None;
85
event.propagate(false);
86
},
87
)
88
.with_children(|parent| {
89
for (label, tab_group, indices) in [
90
// In this group all the buttons have the same `TabIndex` so they will be visited according to their order as children.
91
("TabGroup 0", TabGroup::new(0), [0, 0, 0, 0]),
92
// In this group the `TabIndex`s are reversed so the buttons will be visited in right-to-left order.
93
("TabGroup 2", TabGroup::new(2), [3, 2, 1, 0]),
94
// In this group the orders of the indices and buttons match so the buttons will be visited in left-to-right order.
95
("TabGroup 1", TabGroup::new(1), [0, 1, 2, 3]),
96
// Visit the modal group's buttons in an arbitrary order.
97
("Modal TabGroup", TabGroup::modal(), [0, 3, 1, 2]),
98
] {
99
parent.spawn(Text::new(label));
100
parent
101
.spawn((
102
Node {
103
display: Display::Flex,
104
flex_direction: FlexDirection::Row,
105
column_gap: px(6),
106
margin: UiRect {
107
bottom: px(10),
108
..default()
109
},
110
..default()
111
},
112
tab_group,
113
))
114
.with_children(|parent| {
115
for i in indices {
116
parent
117
.spawn((
118
Button,
119
Node {
120
width: px(200),
121
height: px(65),
122
border: UiRect::all(px(5)),
123
justify_content: JustifyContent::Center,
124
align_items: AlignItems::Center,
125
..default()
126
},
127
BorderColor::all(Color::BLACK),
128
BackgroundColor(NORMAL_BUTTON),
129
TabIndex(i),
130
children![(
131
Text::new(format!("TabIndex {i}")),
132
TextFont {
133
font_size: 20.0,
134
..default()
135
},
136
TextColor(Color::srgb(0.9, 0.9, 0.9)),
137
)],
138
))
139
.observe(
140
|mut event: On<Pointer<Click>>,
141
mut focus: ResMut<InputFocus>| {
142
focus.0 = Some(event.entity());
143
event.propagate(false);
144
},
145
);
146
}
147
});
148
}
149
});
150
}
151
152