Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bevyengine
GitHub Repository: bevyengine/bevy
Path: blob/main/examples/ui/overflow_debug.rs
6596 views
1
//! Tests how different transforms behave when clipped with `Overflow::Hidden`
2
3
use bevy::{input::common_conditions::input_just_pressed, prelude::*, ui::widget::TextUiWriter};
4
use std::f32::consts::{FRAC_PI_2, PI, TAU};
5
6
const CONTAINER_SIZE: f32 = 150.0;
7
const LOOP_LENGTH: f32 = 4.0;
8
9
fn main() {
10
App::new()
11
.add_plugins(DefaultPlugins)
12
.init_resource::<AnimationState>()
13
.add_systems(Startup, setup)
14
.add_systems(
15
Update,
16
(
17
toggle_overflow.run_if(input_just_pressed(KeyCode::KeyO)),
18
next_container_size.run_if(input_just_pressed(KeyCode::KeyS)),
19
update_transform::<Move>,
20
update_transform::<Scale>,
21
update_transform::<Rotate>,
22
update_animation,
23
),
24
)
25
.run();
26
}
27
28
#[derive(Component)]
29
struct Instructions;
30
31
#[derive(Resource, Default)]
32
struct AnimationState {
33
playing: bool,
34
paused_at: f32,
35
paused_total: f32,
36
t: f32,
37
}
38
39
#[derive(Component)]
40
struct Container(u8);
41
42
trait UpdateTransform {
43
fn update(&self, t: f32, transform: &mut UiTransform);
44
}
45
46
#[derive(Component)]
47
struct Move;
48
49
impl UpdateTransform for Move {
50
fn update(&self, t: f32, transform: &mut UiTransform) {
51
transform.translation.x = percent(ops::sin(t * TAU - FRAC_PI_2) * 50.);
52
transform.translation.y = percent(-ops::cos(t * TAU - FRAC_PI_2) * 50.);
53
}
54
}
55
56
#[derive(Component)]
57
struct Scale;
58
59
impl UpdateTransform for Scale {
60
fn update(&self, t: f32, transform: &mut UiTransform) {
61
transform.scale.x = 1.0 + 0.5 * ops::cos(t * TAU).max(0.0);
62
transform.scale.y = 1.0 + 0.5 * ops::cos(t * TAU + PI).max(0.0);
63
}
64
}
65
66
#[derive(Component)]
67
struct Rotate;
68
69
impl UpdateTransform for Rotate {
70
fn update(&self, t: f32, transform: &mut UiTransform) {
71
transform.rotation = Rot2::radians(ops::cos(t * TAU) * 45.0);
72
}
73
}
74
75
fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
76
// Camera
77
78
commands.spawn(Camera2d);
79
80
// Instructions
81
82
let text_font = TextFont::default();
83
84
commands
85
.spawn((
86
Text::new(
87
"Next Overflow Setting (O)\nNext Container Size (S)\nToggle Animation (space)\n\n",
88
),
89
text_font.clone(),
90
Node {
91
position_type: PositionType::Absolute,
92
top: px(12),
93
left: px(12),
94
..default()
95
},
96
Instructions,
97
))
98
.with_child((
99
TextSpan::new(format!("{:?}", Overflow::clip())),
100
text_font.clone(),
101
));
102
103
// Overflow Debug
104
105
commands
106
.spawn(Node {
107
width: percent(100),
108
height: percent(100),
109
justify_content: JustifyContent::Center,
110
align_items: AlignItems::Center,
111
..default()
112
})
113
.with_children(|parent| {
114
parent
115
.spawn(Node {
116
display: Display::Grid,
117
grid_template_columns: RepeatedGridTrack::px(3, CONTAINER_SIZE),
118
grid_template_rows: RepeatedGridTrack::px(2, CONTAINER_SIZE),
119
row_gap: px(80),
120
column_gap: px(80),
121
..default()
122
})
123
.with_children(|parent| {
124
spawn_image(parent, &asset_server, Move);
125
spawn_image(parent, &asset_server, Scale);
126
spawn_image(parent, &asset_server, Rotate);
127
128
spawn_text(parent, &asset_server, Move);
129
spawn_text(parent, &asset_server, Scale);
130
spawn_text(parent, &asset_server, Rotate);
131
});
132
});
133
}
134
135
fn spawn_image(
136
parent: &mut ChildSpawnerCommands,
137
asset_server: &Res<AssetServer>,
138
update_transform: impl UpdateTransform + Component,
139
) {
140
spawn_container(parent, update_transform, |parent| {
141
parent.spawn((
142
ImageNode::new(asset_server.load("branding/bevy_logo_dark_big.png")),
143
Node {
144
height: px(100),
145
position_type: PositionType::Absolute,
146
top: px(-50),
147
left: px(-200),
148
..default()
149
},
150
));
151
});
152
}
153
154
fn spawn_text(
155
parent: &mut ChildSpawnerCommands,
156
asset_server: &Res<AssetServer>,
157
update_transform: impl UpdateTransform + Component,
158
) {
159
spawn_container(parent, update_transform, |parent| {
160
parent.spawn((
161
Text::new("Bevy"),
162
TextFont {
163
font: asset_server.load("fonts/FiraSans-Bold.ttf"),
164
font_size: 100.0,
165
..default()
166
},
167
));
168
});
169
}
170
171
fn spawn_container(
172
parent: &mut ChildSpawnerCommands,
173
update_transform: impl UpdateTransform + Component,
174
spawn_children: impl FnOnce(&mut ChildSpawnerCommands),
175
) {
176
parent
177
.spawn((
178
Node {
179
width: percent(100),
180
height: percent(100),
181
align_items: AlignItems::Center,
182
justify_content: JustifyContent::Center,
183
overflow: Overflow::clip(),
184
..default()
185
},
186
BackgroundColor(Color::srgb(0.25, 0.25, 0.25)),
187
Container(0),
188
))
189
.with_children(|parent| {
190
parent
191
.spawn((
192
Node {
193
align_items: AlignItems::Center,
194
justify_content: JustifyContent::Center,
195
..default()
196
},
197
update_transform,
198
))
199
.with_children(spawn_children);
200
});
201
}
202
203
fn update_animation(
204
mut animation: ResMut<AnimationState>,
205
time: Res<Time>,
206
keys: Res<ButtonInput<KeyCode>>,
207
) {
208
let delta = time.elapsed_secs();
209
210
if keys.just_pressed(KeyCode::Space) {
211
animation.playing = !animation.playing;
212
213
if !animation.playing {
214
animation.paused_at = delta;
215
} else {
216
animation.paused_total += delta - animation.paused_at;
217
}
218
}
219
220
if animation.playing {
221
animation.t = (delta - animation.paused_total) % LOOP_LENGTH / LOOP_LENGTH;
222
}
223
}
224
225
fn update_transform<T: UpdateTransform + Component>(
226
animation: Res<AnimationState>,
227
mut containers: Query<(&mut UiTransform, &T)>,
228
) {
229
for (mut transform, update_transform) in &mut containers {
230
update_transform.update(animation.t, &mut transform);
231
}
232
}
233
234
fn toggle_overflow(
235
mut containers: Query<&mut Node, With<Container>>,
236
instructions: Single<Entity, With<Instructions>>,
237
mut writer: TextUiWriter,
238
) {
239
for mut node in &mut containers {
240
node.overflow = match node.overflow {
241
Overflow {
242
x: OverflowAxis::Visible,
243
y: OverflowAxis::Visible,
244
} => Overflow::clip_y(),
245
Overflow {
246
x: OverflowAxis::Visible,
247
y: OverflowAxis::Clip,
248
} => Overflow::clip_x(),
249
Overflow {
250
x: OverflowAxis::Clip,
251
y: OverflowAxis::Visible,
252
} => Overflow::clip(),
253
_ => Overflow::visible(),
254
};
255
256
let entity = *instructions;
257
*writer.text(entity, 1) = format!("{:?}", node.overflow);
258
}
259
}
260
261
fn next_container_size(mut containers: Query<(&mut Node, &mut Container)>) {
262
for (mut node, mut container) in &mut containers {
263
container.0 = (container.0 + 1) % 3;
264
265
node.width = match container.0 {
266
2 => percent(30),
267
_ => percent(100),
268
};
269
node.height = match container.0 {
270
1 => percent(30),
271
_ => percent(100),
272
};
273
}
274
}
275
276