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