window_settings/
window_settings.rs1#[cfg(feature = "custom_cursor")]
5use bevy::window::{CustomCursor, CustomCursorImage};
6use bevy::{
7 diagnostic::{FrameCount, FrameTimeDiagnosticsPlugin, LogDiagnosticsPlugin},
8 prelude::*,
9 window::{
10 CursorGrabMode, CursorIcon, CursorOptions, PresentMode, SystemCursorIcon, WindowLevel,
11 WindowTheme,
12 },
13};
14
15fn main() {
16 App::new()
17 .add_plugins((
18 DefaultPlugins.set(WindowPlugin {
19 primary_window: Some(Window {
20 title: "I am a window!".into(),
21 name: Some("bevy.app".into()),
22 resolution: (500, 300).into(),
23 present_mode: PresentMode::AutoVsync,
24 fit_canvas_to_parent: true,
26 prevent_default_event_handling: false,
28 window_theme: Some(WindowTheme::Dark),
29 enabled_buttons: bevy::window::EnabledButtons {
30 maximize: false,
31 ..Default::default()
32 },
33 visible: false,
37 ..default()
38 }),
39 ..default()
40 }),
41 LogDiagnosticsPlugin::default(),
42 FrameTimeDiagnosticsPlugin::default(),
43 ))
44 .add_systems(Startup, init_cursor_icons)
45 .add_systems(
46 Update,
47 (
48 change_title,
49 toggle_theme,
50 toggle_cursor,
51 toggle_vsync,
52 toggle_window_controls,
53 cycle_cursor_icon,
54 switch_level,
55 make_visible,
56 ),
57 )
58 .run();
59}
60
61fn make_visible(mut window: Single<&mut Window>, frames: Res<FrameCount>) {
62 if frames.0 == 3 {
64 window.visible = true;
68 }
69}
70
71fn toggle_vsync(input: Res<ButtonInput<KeyCode>>, mut window: Single<&mut Window>) {
74 if input.just_pressed(KeyCode::KeyV) {
75 window.present_mode = if matches!(window.present_mode, PresentMode::AutoVsync) {
76 PresentMode::AutoNoVsync
77 } else {
78 PresentMode::AutoVsync
79 };
80 info!("PRESENT_MODE: {:?}", window.present_mode);
81 }
82}
83
84fn switch_level(input: Res<ButtonInput<KeyCode>>, mut window: Single<&mut Window>) {
92 if input.just_pressed(KeyCode::KeyT) {
93 window.window_level = match window.window_level {
94 WindowLevel::AlwaysOnBottom => WindowLevel::Normal,
95 WindowLevel::Normal => WindowLevel::AlwaysOnTop,
96 WindowLevel::AlwaysOnTop => WindowLevel::AlwaysOnBottom,
97 };
98 info!("WINDOW_LEVEL: {:?}", window.window_level);
99 }
100}
101
102fn toggle_window_controls(input: Res<ButtonInput<KeyCode>>, mut window: Single<&mut Window>) {
108 let toggle_minimize = input.just_pressed(KeyCode::Digit1);
109 let toggle_maximize = input.just_pressed(KeyCode::Digit2);
110 let toggle_close = input.just_pressed(KeyCode::Digit3);
111
112 if toggle_minimize || toggle_maximize || toggle_close {
113 if toggle_minimize {
114 window.enabled_buttons.minimize = !window.enabled_buttons.minimize;
115 }
116 if toggle_maximize {
117 window.enabled_buttons.maximize = !window.enabled_buttons.maximize;
118 }
119 if toggle_close {
120 window.enabled_buttons.close = !window.enabled_buttons.close;
121 }
122 }
123}
124
125fn change_title(mut window: Single<&mut Window>, time: Res<Time>) {
127 window.title = format!(
128 "Seconds since startup: {}",
129 time.elapsed().as_secs_f32().round()
130 );
131}
132
133fn toggle_cursor(mut cursor_options: Single<&mut CursorOptions>, input: Res<ButtonInput<KeyCode>>) {
134 if input.just_pressed(KeyCode::Space) {
135 cursor_options.visible = !cursor_options.visible;
136 cursor_options.grab_mode = match cursor_options.grab_mode {
137 CursorGrabMode::None => CursorGrabMode::Locked,
138 CursorGrabMode::Locked | CursorGrabMode::Confined => CursorGrabMode::None,
139 };
140 }
141}
142
143fn toggle_theme(mut window: Single<&mut Window>, input: Res<ButtonInput<KeyCode>>) {
145 if input.just_pressed(KeyCode::KeyF)
146 && let Some(current_theme) = window.window_theme
147 {
148 window.window_theme = match current_theme {
149 WindowTheme::Light => Some(WindowTheme::Dark),
150 WindowTheme::Dark => Some(WindowTheme::Light),
151 };
152 }
153}
154
155#[derive(Resource)]
156struct CursorIcons(Vec<CursorIcon>);
157
158fn init_cursor_icons(
159 mut commands: Commands,
160 #[cfg(feature = "custom_cursor")] asset_server: Res<AssetServer>,
161) {
162 commands.insert_resource(CursorIcons(vec![
163 SystemCursorIcon::Default.into(),
164 SystemCursorIcon::Pointer.into(),
165 SystemCursorIcon::Wait.into(),
166 SystemCursorIcon::Text.into(),
167 #[cfg(feature = "custom_cursor")]
168 CustomCursor::Image(CustomCursorImage {
169 handle: asset_server.load("branding/icon.png"),
170 hotspot: (128, 128),
171 ..Default::default()
172 })
173 .into(),
174 ]));
175}
176
177fn cycle_cursor_icon(
179 mut commands: Commands,
180 window: Single<Entity, With<Window>>,
181 input: Res<ButtonInput<MouseButton>>,
182 mut index: Local<usize>,
183 cursor_icons: Res<CursorIcons>,
184) {
185 if input.just_pressed(MouseButton::Left) {
186 *index = (*index + 1) % cursor_icons.0.len();
187 commands
188 .entity(*window)
189 .insert(cursor_icons.0[*index].clone());
190 } else if input.just_pressed(MouseButton::Right) {
191 *index = if *index == 0 {
192 cursor_icons.0.len() - 1
193 } else {
194 *index - 1
195 };
196 commands
197 .entity(*window)
198 .insert(cursor_icons.0[*index].clone());
199 }
200}