use std::time::Duration;
use bevy::{
prelude::*,
settings::{
ReflectSettingsGroup, SaveSettingsDeferred, SaveSettingsSync, SettingsGroup, SettingsPlugin,
},
window::{ExitCondition, WindowCloseRequested, WindowMode, WindowResized, WindowResolution},
};
fn main() {
App::new()
.add_plugins(DefaultPlugins.set(WindowPlugin {
exit_condition: ExitCondition::DontExit,
primary_window: Some(Window {
title: "Settings Window".into(),
..default()
}),
..default()
}))
.add_plugins(SettingsPlugin::new(
"org.bevy.examples.persisting_window_settings",
))
.add_systems(Startup, setup)
.add_systems(Update, (on_window_close, update_window_settings))
.add_plugins(init_window_pos)
.run();
}
#[derive(Resource, SettingsGroup, Reflect, Default, Clone, PartialEq)]
#[reflect(Resource, SettingsGroup, Default)]
#[settings_group(group = "window")]
struct WindowSettings {
position: Option<IVec2>,
size: Option<UVec2>,
fullscreen: bool,
}
fn init_window_pos(app: &mut App) {
let world = app.world_mut();
let Some(window_settings) = world.get_resource::<WindowSettings>() else {
return;
};
let window_settings = window_settings.clone();
let Ok(mut window) = world.query::<&mut Window>().single_mut(world) else {
warn!("window not found");
return;
};
if let Some(position) = window_settings.position {
window.position = WindowPosition::new(position);
}
if let Some(size) = window_settings.size {
window.resolution = WindowResolution::new(size.x, size.y);
}
window.mode = if window_settings.fullscreen {
WindowMode::BorderlessFullscreen(MonitorSelection::Current)
} else {
WindowMode::Windowed
};
}
fn setup(mut commands: Commands) {
commands.spawn((Camera::default(), Camera2d));
commands.spawn(Node {
width: percent(100),
height: percent(100),
display: Display::Flex,
flex_direction: FlexDirection::Column,
align_items: AlignItems::Center,
justify_content: JustifyContent::Center,
..default()
});
}
fn update_window_settings(
mut move_events: MessageReader<WindowMoved>,
mut resize_events: MessageReader<WindowResized>,
windows: Query<&mut Window>,
window_settings: ResMut<WindowSettings>,
mut commands: Commands,
) {
let Ok(window) = windows.single() else {
return;
};
let mut window_changed = false;
for _ in move_events.read() {
window_changed = true;
}
for _ in resize_events.read() {
window_changed = true;
}
if window_changed && store_window_settings(window_settings, window) {
commands.queue(SaveSettingsDeferred(Duration::from_secs_f32(0.5)));
}
}
fn store_window_settings(mut window_settings: ResMut<WindowSettings>, window: &Window) -> bool {
window_settings.set_if_neq(WindowSettings {
position: match window.position {
WindowPosition::At(pos) => Some(pos),
_ => None,
},
size: Some(UVec2::new(
window.resolution.width() as u32,
window.resolution.height() as u32,
)),
fullscreen: window.mode != WindowMode::Windowed,
})
}
fn on_window_close(mut close: MessageReader<WindowCloseRequested>, mut commands: Commands) {
if let Some(_close_event) = close.read().next() {
commands.queue(SaveSettingsSync::IfChanged);
commands.write_message(AppExit::Success);
}
}