Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bevyengine
GitHub Repository: bevyengine/bevy
Path: blob/main/examples/ui/ui_scaling.rs
9356 views
1
//! This example illustrates the [`UiScale`] resource from `bevy_ui`.
2
3
use bevy::{color::palettes::css::*, prelude::*};
4
5
use core::time::Duration;
6
7
const SCALE_TIME: u64 = 400;
8
9
fn main() {
10
App::new()
11
.add_plugins(DefaultPlugins)
12
.insert_resource(TargetScale {
13
start_scale: 1.0,
14
target_scale: 1.0,
15
target_time: Timer::new(Duration::from_millis(SCALE_TIME), TimerMode::Once),
16
})
17
.add_systems(Startup, setup)
18
.add_systems(
19
Update,
20
(change_scaling, apply_scaling.after(change_scaling)),
21
)
22
.run();
23
}
24
25
fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
26
commands.spawn(Camera2d);
27
28
let text_font = TextFont {
29
font_size: FontSize::Px(13.),
30
..default()
31
};
32
33
commands
34
.spawn((
35
Node {
36
width: percent(50),
37
height: percent(50),
38
position_type: PositionType::Absolute,
39
left: percent(25),
40
top: percent(25),
41
justify_content: JustifyContent::SpaceAround,
42
align_items: AlignItems::Center,
43
..default()
44
},
45
BackgroundColor(ANTIQUE_WHITE.into()),
46
))
47
.with_children(|parent| {
48
parent
49
.spawn((
50
Node {
51
width: px(40),
52
height: px(40),
53
..default()
54
},
55
BackgroundColor(RED.into()),
56
))
57
.with_children(|parent| {
58
parent.spawn((Text::new("Size!"), text_font, TextColor::BLACK));
59
});
60
parent.spawn((
61
Node {
62
width: percent(15),
63
height: percent(15),
64
..default()
65
},
66
BackgroundColor(BLUE.into()),
67
));
68
parent.spawn((
69
ImageNode::new(asset_server.load("branding/icon.png")),
70
Node {
71
width: px(30),
72
height: px(30),
73
..default()
74
},
75
));
76
});
77
}
78
79
/// System that changes the scale of the ui when pressing up or down on the keyboard.
80
fn change_scaling(input: Res<ButtonInput<KeyCode>>, mut ui_scale: ResMut<TargetScale>) {
81
if input.just_pressed(KeyCode::ArrowUp) {
82
let scale = (ui_scale.target_scale * 2.0).min(8.);
83
ui_scale.set_scale(scale);
84
info!("Scaling up! Scale: {}", ui_scale.target_scale);
85
}
86
if input.just_pressed(KeyCode::ArrowDown) {
87
let scale = (ui_scale.target_scale / 2.0).max(1. / 8.);
88
ui_scale.set_scale(scale);
89
info!("Scaling down! Scale: {}", ui_scale.target_scale);
90
}
91
}
92
93
#[derive(Resource)]
94
struct TargetScale {
95
start_scale: f32,
96
target_scale: f32,
97
target_time: Timer,
98
}
99
100
impl TargetScale {
101
fn set_scale(&mut self, scale: f32) {
102
self.start_scale = self.current_scale();
103
self.target_scale = scale;
104
self.target_time.reset();
105
}
106
107
fn current_scale(&self) -> f32 {
108
let completion = self.target_time.fraction();
109
let t = ease_in_expo(completion);
110
self.start_scale.lerp(self.target_scale, t)
111
}
112
113
fn tick(&mut self, delta: Duration) -> &Self {
114
self.target_time.tick(delta);
115
self
116
}
117
118
fn already_completed(&self) -> bool {
119
self.target_time.is_finished() && !self.target_time.just_finished()
120
}
121
}
122
123
fn apply_scaling(
124
time: Res<Time>,
125
mut target_scale: ResMut<TargetScale>,
126
mut ui_scale: ResMut<UiScale>,
127
) {
128
if target_scale.tick(time.delta()).already_completed() {
129
return;
130
}
131
132
ui_scale.0 = target_scale.current_scale();
133
}
134
135
fn ease_in_expo(x: f32) -> f32 {
136
if x == 0. {
137
0.
138
} else {
139
ops::powf(2.0f32, 5. * x - 5.)
140
}
141
}
142
143