dexterous_developer_bevy_winit/winit_config.rs
1use bevy_ecs::system::Resource;
2use bevy_utils::Duration;
3
4/// A resource for configuring usage of the [`winit`] library.
5#[derive(Debug, Resource)]
6pub struct WinitSettings {
7 /// Configures `winit` to return control to the caller after exiting the
8 /// event loop, enabling [`App::run()`](bevy_app::App::run()) to return.
9 ///
10 /// By default, [`return_from_run`](Self::return_from_run) is `false` and *Bevy*
11 /// will use `winit`'s
12 /// [`EventLoop::run()`](https://docs.rs/winit/latest/winit/event_loop/struct.EventLoop.html#method.run)
13 /// to initiate the event loop.
14 /// [`EventLoop::run()`](https://docs.rs/winit/latest/winit/event_loop/struct.EventLoop.html#method.run)
15 /// will never return but will terminate the process after the event loop exits.
16 ///
17 /// Setting [`return_from_run`](Self::return_from_run) to `true` will cause *Bevy*
18 /// to use `winit`'s
19 /// [`EventLoopExtRunReturn::run_return()`](https://docs.rs/winit/latest/winit/platform/run_return/trait.EventLoopExtRunReturn.html#tymethod.run_return)
20 /// instead which is strongly discouraged by the `winit` authors.
21 ///
22 /// # Supported platforms
23 ///
24 /// This feature is only available on the following desktop `target_os` configurations:
25 /// `windows`, `macos`, `linux`, `dragonfly`, `freebsd`, `netbsd`, and `openbsd`.
26 ///
27 /// Setting [`return_from_run`](Self::return_from_run) to `true` on
28 /// unsupported platforms will cause [`App::run()`](bevy_app::App::run()) to panic!
29 pub return_from_run: bool,
30 /// Configures how the winit event loop updates while the window is focused.
31 pub focused_mode: UpdateMode,
32 /// Configures how the winit event loop updates while the window is *not* focused.
33 pub unfocused_mode: UpdateMode,
34}
35impl WinitSettings {
36 /// Configure winit with common settings for a game.
37 pub fn game() -> Self {
38 WinitSettings::default()
39 }
40
41 /// Configure winit with common settings for a desktop application.
42 pub fn desktop_app() -> Self {
43 WinitSettings {
44 focused_mode: UpdateMode::Reactive {
45 max_wait: Duration::from_secs(5),
46 },
47 unfocused_mode: UpdateMode::ReactiveLowPower {
48 max_wait: Duration::from_secs(60),
49 },
50 ..Default::default()
51 }
52 }
53
54 /// Gets the configured [`UpdateMode`] depending on whether the window is focused or not
55 pub fn update_mode(&self, focused: bool) -> &UpdateMode {
56 match focused {
57 true => &self.focused_mode,
58 false => &self.unfocused_mode,
59 }
60 }
61}
62impl Default for WinitSettings {
63 fn default() -> Self {
64 WinitSettings {
65 return_from_run: false,
66 focused_mode: UpdateMode::Continuous,
67 unfocused_mode: UpdateMode::Continuous,
68 }
69 }
70}
71
72/// Configure how the winit event loop should update.
73#[derive(Debug)]
74pub enum UpdateMode {
75 /// The event loop will update continuously, running as fast as possible.
76 Continuous,
77 /// The event loop will only update if there is a winit event, a redraw is requested, or the
78 /// maximum wait time has elapsed.
79 ///
80 /// ## Note
81 ///
82 /// Once the app has executed all bevy systems and reaches the end of the event loop, there is
83 /// no way to force the app to wake and update again, unless a `winit` event (such as user
84 /// input, or the window being resized) is received or the time limit is reached.
85 Reactive {
86 /// The maximum time to wait before the event loop runs again.
87 ///
88 /// Note that Bevy will wait indefinitely if the duration is too high (such as [`Duration::MAX`]).
89 max_wait: Duration,
90 },
91 /// The event loop will only update if there is a winit event from direct interaction with the
92 /// window (e.g. mouseover), a redraw is requested, or the maximum wait time has elapsed.
93 ///
94 /// ## Note
95 ///
96 /// Once the app has executed all bevy systems and reaches the end of the event loop, there is
97 /// no way to force the app to wake and update again, unless a `winit` event (such as user
98 /// input, or the window being resized) is received or the time limit is reached.
99 ///
100 /// ## Differences from [`UpdateMode::Reactive`]
101 ///
102 /// Unlike [`UpdateMode::Reactive`], this mode will ignore winit events that aren't directly
103 /// caused by interaction with the window. For example, you might want to use this mode when the
104 /// window is not focused, to only re-draw your bevy app when the cursor is over the window, but
105 /// not when the mouse moves somewhere else on the screen. This helps to significantly reduce
106 /// power consumption by only updated the app when absolutely necessary.
107 ReactiveLowPower {
108 /// The maximum time to wait before the event loop runs again.
109 ///
110 /// Note that Bevy will wait indefinitely if the duration is too high (such as [`Duration::MAX`]).
111 max_wait: Duration,
112 },
113}