//! This example illustrates how to run a winit window in a reactive, low power mode. //! //! This is useful for making desktop applications, or any other program that doesn't need to be //! running the event loop non-stop. use bevy::{ prelude::*, utils::Duration, window::{PresentMode, RequestRedraw, WindowPlugin}, winit::{EventLoopProxy, WinitSettings}, }; fn main() { App::new() // Continuous rendering for games - bevy's default. .insert_resource(WinitSettings::game()) // Power-saving reactive rendering for applications. .insert_resource(WinitSettings::desktop_app()) // You can also customize update behavior with the fields of [`WinitSettings`] .insert_resource(WinitSettings { focused_mode: bevy::winit::UpdateMode::Continuous, unfocused_mode: bevy::winit::UpdateMode::ReactiveLowPower { wait: Duration::from_millis(10), }, }) .insert_resource(ExampleMode::Game) .add_plugins(DefaultPlugins.set(WindowPlugin { primary_window: Some(Window { // Turn off vsync to maximize CPU/GPU usage present_mode: PresentMode::AutoNoVsync, ..default() }), ..default() })) .add_systems(Startup, test_setup::setup) .add_systems( Update, ( test_setup::cycle_modes, test_setup::rotate_cube, test_setup::update_text, update_winit, ), ) .run(); } #[derive(Resource, Debug)] enum ExampleMode { Game, Application, ApplicationWithRedraw, } /// Update winit based on the current `ExampleMode` fn update_winit( mode: Res, mut winit_config: ResMut, event_loop_proxy: NonSend, ) { use ExampleMode::*; *winit_config = match *mode { Game => { // In the default `WinitSettings::game()` mode: // * When focused: the event loop runs as fast as possible // * When not focused: the app will update when the window is directly interacted with // (e.g. the mouse hovers over a visible part of the out of focus window), a // [`RequestRedraw`] event is received, or one sixtieth of a second has passed // without the app updating (60 Hz refresh rate max). WinitSettings::game() } Application => { // While in `WinitSettings::desktop_app()` mode: // * When focused: the app will update any time a winit event (e.g. the window is // moved/resized, the mouse moves, a button is pressed, etc.), a [`RequestRedraw`] // event is received, or after 5 seconds if the app has not updated. // * When not focused: the app will update when the window is directly interacted with // (e.g. the mouse hovers over a visible part of the out of focus window), a // [`RequestRedraw`] event is received, or one minute has passed without the app // updating. WinitSettings::desktop_app() } ApplicationWithRedraw => { // Sending a `RequestRedraw` event is useful when you want the app to update the next // frame regardless of any user input. For example, your application might use // `WinitSettings::desktop_app()` to reduce power use, but UI animations need to play even // when there are no inputs, so you send redraw requests while the animation is playing. // Note that in this example the RequestRedraw winit event will make the app run in the same // way as continuous let _ = event_loop_proxy.send_event(RequestRedraw); WinitSettings::desktop_app() } }; } /// Everything in this module is for setting up and animating the scene, and is not important to the /// demonstrated features. pub(crate) mod test_setup { use crate::ExampleMode; use bevy::{ color::palettes::basic::{LIME, YELLOW}, prelude::*, window::RequestRedraw, }; /// Switch between update modes when the mouse is clicked. pub(crate) fn cycle_modes( mut mode: ResMut, button_input: Res>, ) { if button_input.just_pressed(KeyCode::Space) { *mode = match *mode { ExampleMode::Game => ExampleMode::Application, ExampleMode::Application => ExampleMode::ApplicationWithRedraw, ExampleMode::ApplicationWithRedraw => ExampleMode::Game, }; } } #[derive(Component)] pub(crate) struct Rotator; /// Rotate the cube to make it clear when the app is updating pub(crate) fn rotate_cube( time: Res