| 1 |
|
| 2 |
|
| 3 |
|
| 4 |
|
| 5 |
|
| 6 |
|
| 7 |
|
| 8 |
use std::time::Duration; |
| 9 |
|
| 10 |
use bevy::{ |
| 11 |
prelude::*, |
| 12 |
settings::{ |
| 13 |
ReflectSettingsGroup, SaveSettingsDeferred, SaveSettingsSync, SettingsGroup, SettingsPlugin, |
| 14 |
}, |
| 15 |
window::{ExitCondition, WindowCloseRequested, WindowMode, WindowResized, WindowResolution}, |
| 16 |
}; |
| 17 |
|
| 18 |
fn main() { |
| 19 |
App::new() |
| 20 |
.add_plugins(DefaultPlugins.set(WindowPlugin { |
| 21 |
|
| 22 |
exit_condition: ExitCondition::DontExit, |
| 23 |
primary_window: Some(Window { |
| 24 |
title: "Settings Window".into(), |
| 25 |
..default() |
| 26 |
}), |
| 27 |
..default() |
| 28 |
})) |
| 29 |
.add_plugins(SettingsPlugin::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 |
} |
| 37 |
|
| 38 |
|
| 39 |
#[derive(Resource, SettingsGroup, Reflect, Default, Clone, PartialEq)] |
| 40 |
#[reflect(Resource, SettingsGroup, Default)] |
| 41 |
#[settings_group(group = "window")] |
| 42 |
struct WindowSettings { |
| 43 |
position: Option<IVec2>, |
| 44 |
size: Option<UVec2>, |
| 45 |
fullscreen: bool, |
| 46 |
} |
| 47 |
|
| 48 |
|
| 49 |
fn init_window_pos(app: &mut App) { |
| 50 |
let world = app.world_mut(); |
| 51 |
let Some(window_settings) = world.get_resource::<WindowSettings>() else { |
| 52 |
return; |
| 53 |
}; |
| 54 |
let window_settings = window_settings.clone(); |
| 55 |
|
| 56 |
let Ok(mut window) = world.query::<&mut Window>().single_mut(world) else { |
| 57 |
warn!("window not found"); |
| 58 |
return; |
| 59 |
}; |
| 60 |
|
| 61 |
if let Some(position) = window_settings.position { |
| 62 |
window.position = WindowPosition::new(position); |
| 63 |
} |
| 64 |
|
| 65 |
if let Some(size) = window_settings.size { |
| 66 |
window.resolution = WindowResolution::new(size.x, size.y); |
| 67 |
} |
| 68 |
|
| 69 |
window.mode = if window_settings.fullscreen { |
| 70 |
WindowMode::BorderlessFullscreen(MonitorSelection::Current) |
| 71 |
} else { |
| 72 |
WindowMode::Windowed |
| 73 |
}; |
| 74 |
} |
| 75 |
|
| 76 |
fn setup(mut commands: Commands) { |
| 77 |
commands.spawn((Camera::default(), Camera2d)); |
| 78 |
commands.spawn(Node { |
| 79 |
width: percent(100), |
| 80 |
height: percent(100), |
| 81 |
display: Display::Flex, |
| 82 |
flex_direction: FlexDirection::Column, |
| 83 |
align_items: AlignItems::Center, |
| 84 |
justify_content: JustifyContent::Center, |
| 85 |
..default() |
| 86 |
}); |
| 87 |
} |
| 88 |
|
| 89 |
|
| 90 |
fn update_window_settings( |
| 91 |
mut move_events: MessageReader<WindowMoved>, |
| 92 |
mut resize_events: MessageReader<WindowResized>, |
| 93 |
windows: Query<&mut Window>, |
| 94 |
window_settings: ResMut<WindowSettings>, |
| 95 |
mut commands: Commands, |
| 96 |
) { |
| 97 |
let Ok(window) = windows.single() else { |
| 98 |
return; |
| 99 |
}; |
| 100 |
|
| 101 |
let mut window_changed = false; |
| 102 |
for _ in move_events.read() { |
| 103 |
window_changed = true; |
| 104 |
} |
| 105 |
|
| 106 |
for _ in resize_events.read() { |
| 107 |
window_changed = true; |
| 108 |
} |
| 109 |
|
| 110 |
if window_changed && store_window_settings(window_settings, window) { |
| 111 |
commands.queue(SaveSettingsDeferred(Duration::from_secs_f32(0.5))); |
| 112 |
} |
| 113 |
} |
| 114 |
|
| 115 |
fn store_window_settings(mut window_settings: ResMut<WindowSettings>, window: &Window) -> bool { |
| 116 |
window_settings.set_if_neq(WindowSettings { |
| 117 |
position: match window.position { |
| 118 |
WindowPosition::At(pos) => Some(pos), |
| 119 |
_ => None, |
| 120 |
}, |
| 121 |
size: Some(UVec2::new( |
| 122 |
window.resolution.width() as u32, |
| 123 |
window.resolution.height() as u32, |
| 124 |
)), |
| 125 |
fullscreen: window.mode != WindowMode::Windowed, |
| 126 |
}) |
| 127 |
} |
| 128 |
|
| 129 |
fn on_window_close(mut close: MessageReader<WindowCloseRequested>, mut commands: Commands) { |
| 130 |
|
| 131 |
if let Some(_close_event) = close.read().next() { |
| 132 |
commands.queue(SaveSettingsSync::IfChanged); |
| 133 |
commands.write_message(AppExit::Success); |
| 134 |
} |
| 135 |
} |