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