Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add the ability to request a redraw from an external source #12197

Merged
merged 5 commits into from
Mar 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 18 additions & 6 deletions crates/bevy_winit/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ pub struct WinitPlugin {

impl Plugin for WinitPlugin {
fn build(&self, app: &mut App) {
let mut event_loop_builder = EventLoopBuilder::<()>::with_user_event();
let mut event_loop_builder = EventLoopBuilder::<UserEvent>::with_user_event();

// linux check is needed because x11 might be enabled on other platforms.
#[cfg(all(target_os = "linux", feature = "x11"))]
Expand Down Expand Up @@ -243,6 +243,15 @@ type CreateWindowParams<'w, 's, F = ()> = (
Res<'w, AccessibilityRequested>,
);

/// The [`winit::event_loop::EventLoopProxy`] with the specific [`winit::event::Event::UserEvent`] used in the [`winit_runner`].
///
/// The `EventLoopProxy` can be used to request a redraw from outside bevy.
///
/// Use `NonSend<EventLoopProxy>` to receive this resource.
pub type EventLoopProxy = winit::event_loop::EventLoopProxy<UserEvent>;

type UserEvent = RequestRedraw;

/// The default [`App::runner`] for the [`WinitPlugin`] plugin.
///
/// Overriding the app's [runner](bevy_app::App::runner) while using `WinitPlugin` will bypass the
Expand All @@ -255,7 +264,7 @@ pub fn winit_runner(mut app: App) {

let event_loop = app
.world
.remove_non_send_resource::<EventLoop<()>>()
.remove_non_send_resource::<EventLoop<UserEvent>>()
.unwrap();

app.world
Expand All @@ -281,7 +290,7 @@ pub fn winit_runner(mut app: App) {
SystemState::<CreateWindowParams<Added<Window>>>::from_world(&mut app.world);
let mut winit_events = Vec::default();
// set up the event loop
let event_handler = move |event, event_loop: &EventLoopWindowTarget<()>| {
let event_handler = move |event, event_loop: &EventLoopWindowTarget<UserEvent>| {
handle_winit_event(
&mut app,
&mut app_exit_event_reader,
Expand Down Expand Up @@ -318,8 +327,8 @@ fn handle_winit_event(
focused_windows_state: &mut SystemState<(Res<WinitSettings>, Query<&Window>)>,
redraw_event_reader: &mut ManualEventReader<RequestRedraw>,
winit_events: &mut Vec<WinitEvent>,
event: Event<()>,
event_loop: &EventLoopWindowTarget<()>,
event: Event<UserEvent>,
event_loop: &EventLoopWindowTarget<UserEvent>,
) {
#[cfg(feature = "trace")]
let _span = bevy_utils::tracing::info_span!("winit event_handler").entered();
Expand Down Expand Up @@ -698,6 +707,9 @@ fn handle_winit_event(
event_loop.set_control_flow(ControlFlow::Wait);
}
}
Event::UserEvent(RequestRedraw) => {
runner_state.redraw_requested = true;
}
_ => (),
}

Expand All @@ -712,7 +724,7 @@ fn run_app_update_if_should(
runner_state: &mut WinitAppRunnerState,
app: &mut App,
focused_windows_state: &mut SystemState<(Res<WinitSettings>, Query<&Window>)>,
event_loop: &EventLoopWindowTarget<()>,
event_loop: &EventLoopWindowTarget<UserEvent>,
create_window: &mut SystemState<CreateWindowParams<Added<Window>>>,
app_exit_event_reader: &mut ManualEventReader<AppExit>,
redraw_event_reader: &mut ManualEventReader<RequestRedraw>,
Expand Down
2 changes: 1 addition & 1 deletion crates/bevy_winit/src/system.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ use crate::{
/// default values.
#[allow(clippy::too_many_arguments)]
pub(crate) fn create_windows<F: QueryFilter + 'static>(
event_loop: &EventLoopWindowTarget<()>,
event_loop: &EventLoopWindowTarget<crate::UserEvent>,
(
mut commands,
mut created_windows,
Expand Down
4 changes: 4 additions & 0 deletions crates/bevy_winit/src/winit_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ impl WinitSettings {
///
/// [`Reactive`](UpdateMode::Reactive) if windows have focus,
/// [`ReactiveLowPower`](UpdateMode::ReactiveLowPower) otherwise.
///
/// Use the [`EventLoopProxy`](crate::EventLoopProxy) to request a redraw from outside bevy.
pub fn desktop_app() -> Self {
WinitSettings {
focused_mode: UpdateMode::Reactive {
Expand Down Expand Up @@ -72,6 +74,7 @@ pub enum UpdateMode {
/// - a redraw has been requested by [`RequestRedraw`](bevy_window::RequestRedraw)
/// - new [window](`winit::event::WindowEvent`) or [raw input](`winit::event::DeviceEvent`)
/// events have appeared
/// - a redraw has been requested with the [`EventLoopProxy`](crate::EventLoopProxy)
Reactive {
/// The approximate time from the start of one update to the next.
///
Expand All @@ -84,6 +87,7 @@ pub enum UpdateMode {
/// - `wait` time has elapsed since the previous update
/// - a redraw has been requested by [`RequestRedraw`](bevy_window::RequestRedraw)
/// - new [window events](`winit::event::WindowEvent`) have appeared
/// - a redraw has been requested with the [`EventLoopProxy`](crate::EventLoopProxy)
///
/// **Note:** Unlike [`Reactive`](`UpdateMode::Reactive`), this mode will ignore events that
/// don't come from interacting with a window, like [`MouseMotion`](winit::event::DeviceEvent::MouseMotion).
Expand Down
2 changes: 1 addition & 1 deletion crates/bevy_winit/src/winit_windows.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ impl WinitWindows {
/// Creates a `winit` window and associates it with our entity.
pub fn create_window(
&mut self,
event_loop: &winit::event_loop::EventLoopWindowTarget<()>,
event_loop: &winit::event_loop::EventLoopWindowTarget<crate::UserEvent>,
entity: Entity,
window: &Window,
adapters: &mut AccessKitAdapters,
Expand Down