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