Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bevyengine
GitHub Repository: bevyengine/bevy
Path: blob/main/examples/window/persisting_window_settings.rs
30632 views
1
//! Demonstrates persistence of user preferences for saving window position.
2
//!
3
//! This app saves the app window’s settings to preferences. You may resize the window, move it
4
//! around, and make it full screen; this example will remember those settings.
5
//!
6
//! If you close the app and restart it, the app should initialize back to the previous window position,
7
//! size, and mode (i.e. fullscreen) it had at closing.
8
use std::time::Duration;
9
10
use bevy::{
11
prelude::*,
12
settings::{
13
PreferencesPlugin, ReflectSettingsGroup, SavePreferencesDeferred, SavePreferencesSync,
14
SettingsGroup,
15
},
16
window::{ExitCondition, WindowCloseRequested, WindowMode, WindowResized, WindowResolution},
17
};
18
19
fn main() {
20
App::new()
21
.add_plugins(DefaultPlugins.set(WindowPlugin {
22
// We want to intercept the exit so that we can save prefs.
23
exit_condition: ExitCondition::DontExit,
24
primary_window: Some(Window {
25
title: "Prefs Window".into(),
26
..default()
27
}),
28
..default()
29
}))
30
.add_plugins(PreferencesPlugin::new(
31
"org.bevy.examples.persisting_window_settings",
32
))
33
.add_systems(Startup, setup)
34
.add_systems(Update, (on_window_close, update_window_settings))
35
.add_plugins(init_window_pos)
36
.run();
37
}
38
39
/// Settings group which remembers the current window position and size
40
#[derive(Resource, SettingsGroup, Reflect, Default, Clone, PartialEq)]
41
#[reflect(Resource, SettingsGroup, Default)]
42
#[settings_group(group = "window")]
43
struct WindowSettings {
44
position: Option<IVec2>,
45
size: Option<UVec2>,
46
fullscreen: bool,
47
}
48
49
/// A "glue" plugin that copies the window settings to the actual window entity.
50
fn init_window_pos(app: &mut App) {
51
let world = app.world_mut();
52
let Some(window_settings) = world.get_resource::<WindowSettings>() else {
53
return;
54
};
55
let window_settings = window_settings.clone();
56
57
let Ok(mut window) = world.query::<&mut Window>().single_mut(world) else {
58
warn!("window not found");
59
return;
60
};
61
62
if let Some(position) = window_settings.position {
63
window.position = WindowPosition::new(position);
64
}
65
66
if let Some(size) = window_settings.size {
67
window.resolution = WindowResolution::new(size.x, size.y);
68
}
69
70
window.mode = if window_settings.fullscreen {
71
WindowMode::BorderlessFullscreen(MonitorSelection::Current)
72
} else {
73
WindowMode::Windowed
74
};
75
}
76
77
fn setup(mut commands: Commands) {
78
commands.spawn((Camera::default(), Camera2d));
79
commands.spawn(Node {
80
width: percent(100),
81
height: percent(100),
82
display: Display::Flex,
83
flex_direction: FlexDirection::Column,
84
align_items: AlignItems::Center,
85
justify_content: JustifyContent::Center,
86
..default()
87
});
88
}
89
90
/// System which keeps the window settings up to date when the user resizes or moves the window.
91
fn update_window_settings(
92
mut move_events: MessageReader<WindowMoved>,
93
mut resize_events: MessageReader<WindowResized>,
94
windows: Query<&mut Window>,
95
window_settings: ResMut<WindowSettings>,
96
mut commands: Commands,
97
) {
98
let Ok(window) = windows.single() else {
99
return;
100
};
101
102
let mut window_changed = false;
103
for _ in move_events.read() {
104
window_changed = true;
105
}
106
107
for _ in resize_events.read() {
108
window_changed = true;
109
}
110
111
if window_changed && store_window_settings(window_settings, window) {
112
commands.queue(SavePreferencesDeferred(Duration::from_secs_f32(0.5)));
113
}
114
}
115
116
fn store_window_settings(mut window_settings: ResMut<WindowSettings>, window: &Window) -> bool {
117
window_settings.set_if_neq(WindowSettings {
118
position: match window.position {
119
WindowPosition::At(pos) => Some(pos),
120
_ => None,
121
},
122
size: Some(UVec2::new(
123
window.resolution.width() as u32,
124
window.resolution.height() as u32,
125
)),
126
fullscreen: window.mode != WindowMode::Windowed,
127
})
128
}
129
130
fn on_window_close(mut close: MessageReader<WindowCloseRequested>, mut commands: Commands) {
131
// Save preferences immediately, then quit.
132
if let Some(_close_event) = close.read().next() {
133
commands.queue(SavePreferencesSync::IfChanged);
134
commands.queue(ExitAfterSave);
135
}
136
}
137
138
struct ExitAfterSave;
139
140
impl Command for ExitAfterSave {
141
type Out = ();
142
143
fn apply(self, world: &mut World) {
144
world.write_message(AppExit::Success);
145
}
146
}
147
148