#[cfg(feature = "custom_cursor")] use bevy::window::{CustomCursor, CustomCursorImage}; use bevy::{ diagnostic::{FrameCount, FrameTimeDiagnosticsPlugin, LogDiagnosticsPlugin}, prelude::*, window::{ CursorGrabMode, CursorIcon, CursorOptions, PresentMode, SystemCursorIcon, WindowLevel, WindowTheme, }, }; fn main() { App::new() .add_plugins(( DefaultPlugins.set(WindowPlugin { primary_window: Some(Window { title: "I am a window!".into(), name: Some("bevy.app".into()), resolution: (500, 300).into(), present_mode: PresentMode::AutoVsync, fit_canvas_to_parent: true, prevent_default_event_handling: false, window_theme: Some(WindowTheme::Dark), enabled_buttons: bevy::window::EnabledButtons { maximize: false, ..Default::default() }, visible: false, ..default() }), ..default() }), LogDiagnosticsPlugin::default(), FrameTimeDiagnosticsPlugin::default(), )) .add_systems(Startup, init_cursor_icons) .add_systems( Update, ( change_title, toggle_theme, toggle_cursor, toggle_vsync, toggle_window_controls, cycle_cursor_icon, switch_level, make_visible, ), ) .run(); } fn make_visible(mut window: Single<&mut Window>, frames: Res<FrameCount>) { if frames.0 == 3 { window.visible = true; } } fn toggle_vsync(input: Res<ButtonInput<KeyCode>>, mut window: Single<&mut Window>) { if input.just_pressed(KeyCode::KeyV) { window.present_mode = if matches!(window.present_mode, PresentMode::AutoVsync) { PresentMode::AutoNoVsync } else { PresentMode::AutoVsync }; info!("PRESENT_MODE: {:?}", window.present_mode); } } fn switch_level(input: Res<ButtonInput<KeyCode>>, mut window: Single<&mut Window>) { if input.just_pressed(KeyCode::KeyT) { window.window_level = match window.window_level { WindowLevel::AlwaysOnBottom => WindowLevel::Normal, WindowLevel::Normal => WindowLevel::AlwaysOnTop, WindowLevel::AlwaysOnTop => WindowLevel::AlwaysOnBottom, }; info!("WINDOW_LEVEL: {:?}", window.window_level); } } fn toggle_window_controls(input: Res<ButtonInput<KeyCode>>, mut window: Single<&mut Window>) { let toggle_minimize = input.just_pressed(KeyCode::Digit1); let toggle_maximize = input.just_pressed(KeyCode::Digit2); let toggle_close = input.just_pressed(KeyCode::Digit3); if toggle_minimize || toggle_maximize || toggle_close { if toggle_minimize { window.enabled_buttons.minimize = !window.enabled_buttons.minimize; } if toggle_maximize { window.enabled_buttons.maximize = !window.enabled_buttons.maximize; } if toggle_close { window.enabled_buttons.close = !window.enabled_buttons.close; } } } fn change_title(mut window: Single<&mut Window>, time: Res<Time>) { window.title = format!( "Seconds since startup: {}", time.elapsed().as_secs_f32().round() ); } fn toggle_cursor(mut cursor_options: Single<&mut CursorOptions>, input: Res<ButtonInput<KeyCode>>) { if input.just_pressed(KeyCode::Space) { cursor_options.visible = !cursor_options.visible; cursor_options.grab_mode = match cursor_options.grab_mode { CursorGrabMode::None => CursorGrabMode::Locked, CursorGrabMode::Locked | CursorGrabMode::Confined => CursorGrabMode::None, }; } } fn toggle_theme(mut window: Single<&mut Window>, input: Res<ButtonInput<KeyCode>>) { if input.just_pressed(KeyCode::KeyF) && let Some(current_theme) = window.window_theme { window.window_theme = match current_theme { WindowTheme::Light => Some(WindowTheme::Dark), WindowTheme::Dark => Some(WindowTheme::Light), }; } } #[derive(Resource)] struct CursorIcons(Vec<CursorIcon>); fn init_cursor_icons( mut commands: Commands, #[cfg(feature = "custom_cursor")] asset_server: Res<AssetServer>, ) { commands.insert_resource(CursorIcons(vec![ SystemCursorIcon::Default.into(), SystemCursorIcon::Pointer.into(), SystemCursorIcon::Wait.into(), SystemCursorIcon::Text.into(), #[cfg(feature = "custom_cursor")] CustomCursor::Image(CustomCursorImage { handle: asset_server.load("branding/icon.png"), hotspot: (128, 128), ..Default::default() }) .into(), ])); } fn cycle_cursor_icon( mut commands: Commands, window: Single<Entity, With<Window>>, input: Res<ButtonInput<MouseButton>>, mut index: Local<usize>, cursor_icons: Res<CursorIcons>, ) { if input.just_pressed(MouseButton::Left) { *index = (*index + 1) % cursor_icons.0.len(); commands .entity(*window) .insert(cursor_icons.0[*index].clone()); } else if input.just_pressed(MouseButton::Right) { *index = if *index == 0 { cursor_icons.0.len() - 1 } else { *index - 1 }; commands .entity(*window) .insert(cursor_icons.0[*index].clone()); } }