Add the ability to request a redraw from an external source (#12197)
Hi, this is a minimal implementation of #12159. I wasn't sure if the `EventLoopProxy` should be wrapped somewhat to make it more explicit. Minimal implementation of #12159 When using `UpdateMode::Reactive` it is currently not possible to request a redraw when a long running task is finished or an external source has new data. This makes the following possible which will then run an app update once ``` rust // EventLoopProxy is Send on most architectures // The EventLoopProxy can also be saved in a thread local for WASM or a static in other architecturecs pub fn example(proxy: NonSend<EventLoopProxy<()>>) { let clone: EventLoopProxy<()> = proxy.clone(); thread::spawn(move || { // do long work clone.send_event(()); }); } ``` By using the EventLoopProxy one can manually send events from external threads to the event loop as `UserEvent`s. This simply sets redraw_requested when a `UserEvent` is received. - Added the ability to request a redraw from an external source --------- Co-authored-by: Kellner, Robin <Robin.Kellner@vector.com>
This commit is contained in:
parent
f4df8b8545
commit
db9d84fb2f
@ -81,7 +81,7 @@ pub struct WinitPlugin {
|
|||||||
|
|
||||||
impl Plugin for WinitPlugin {
|
impl Plugin for WinitPlugin {
|
||||||
fn build(&self, app: &mut App) {
|
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.
|
// linux check is needed because x11 might be enabled on other platforms.
|
||||||
#[cfg(all(target_os = "linux", feature = "x11"))]
|
#[cfg(all(target_os = "linux", feature = "x11"))]
|
||||||
@ -240,6 +240,15 @@ type CreateWindowParams<'w, 's, F = ()> = (
|
|||||||
Res<'w, AccessibilityRequested>,
|
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.
|
/// The default [`App::runner`] for the [`WinitPlugin`] plugin.
|
||||||
///
|
///
|
||||||
/// Overriding the app's [runner](bevy_app::App::runner) while using `WinitPlugin` will bypass the
|
/// Overriding the app's [runner](bevy_app::App::runner) while using `WinitPlugin` will bypass the
|
||||||
@ -252,7 +261,7 @@ pub fn winit_runner(mut app: App) {
|
|||||||
|
|
||||||
let event_loop = app
|
let event_loop = app
|
||||||
.world
|
.world
|
||||||
.remove_non_send_resource::<EventLoop<()>>()
|
.remove_non_send_resource::<EventLoop<UserEvent>>()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
app.world
|
app.world
|
||||||
@ -277,7 +286,7 @@ pub fn winit_runner(mut app: App) {
|
|||||||
let mut create_window =
|
let mut create_window =
|
||||||
SystemState::<CreateWindowParams<Added<Window>>>::from_world(&mut app.world);
|
SystemState::<CreateWindowParams<Added<Window>>>::from_world(&mut app.world);
|
||||||
// set up the event loop
|
// 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(
|
handle_winit_event(
|
||||||
&mut app,
|
&mut app,
|
||||||
&mut app_exit_event_reader,
|
&mut app_exit_event_reader,
|
||||||
@ -312,8 +321,8 @@ fn handle_winit_event(
|
|||||||
)>,
|
)>,
|
||||||
focused_windows_state: &mut SystemState<(Res<WinitSettings>, Query<&Window>)>,
|
focused_windows_state: &mut SystemState<(Res<WinitSettings>, Query<&Window>)>,
|
||||||
redraw_event_reader: &mut ManualEventReader<RequestRedraw>,
|
redraw_event_reader: &mut ManualEventReader<RequestRedraw>,
|
||||||
event: Event<()>,
|
event: Event<UserEvent>,
|
||||||
event_loop: &EventLoopWindowTarget<()>,
|
event_loop: &EventLoopWindowTarget<UserEvent>,
|
||||||
) {
|
) {
|
||||||
#[cfg(feature = "trace")]
|
#[cfg(feature = "trace")]
|
||||||
let _span = bevy_utils::tracing::info_span!("winit event_handler").entered();
|
let _span = bevy_utils::tracing::info_span!("winit event_handler").entered();
|
||||||
@ -690,6 +699,9 @@ fn handle_winit_event(
|
|||||||
event_loop.set_control_flow(ControlFlow::Wait);
|
event_loop.set_control_flow(ControlFlow::Wait);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Event::UserEvent(RequestRedraw) => {
|
||||||
|
runner_state.redraw_requested = true;
|
||||||
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -698,7 +710,7 @@ fn run_app_update_if_should(
|
|||||||
runner_state: &mut WinitAppRunnerState,
|
runner_state: &mut WinitAppRunnerState,
|
||||||
app: &mut App,
|
app: &mut App,
|
||||||
focused_windows_state: &mut SystemState<(Res<WinitSettings>, Query<&Window>)>,
|
focused_windows_state: &mut SystemState<(Res<WinitSettings>, Query<&Window>)>,
|
||||||
event_loop: &EventLoopWindowTarget<()>,
|
event_loop: &EventLoopWindowTarget<UserEvent>,
|
||||||
create_window: &mut SystemState<CreateWindowParams<Added<Window>>>,
|
create_window: &mut SystemState<CreateWindowParams<Added<Window>>>,
|
||||||
app_exit_event_reader: &mut ManualEventReader<AppExit>,
|
app_exit_event_reader: &mut ManualEventReader<AppExit>,
|
||||||
redraw_event_reader: &mut ManualEventReader<RequestRedraw>,
|
redraw_event_reader: &mut ManualEventReader<RequestRedraw>,
|
||||||
|
@ -32,7 +32,7 @@ use crate::{
|
|||||||
/// default values.
|
/// default values.
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
pub(crate) fn create_windows<F: QueryFilter + 'static>(
|
pub(crate) fn create_windows<F: QueryFilter + 'static>(
|
||||||
event_loop: &EventLoopWindowTarget<()>,
|
event_loop: &EventLoopWindowTarget<crate::UserEvent>,
|
||||||
(
|
(
|
||||||
mut commands,
|
mut commands,
|
||||||
mut created_windows,
|
mut created_windows,
|
||||||
|
@ -28,6 +28,8 @@ impl WinitSettings {
|
|||||||
///
|
///
|
||||||
/// [`Reactive`](UpdateMode::Reactive) if windows have focus,
|
/// [`Reactive`](UpdateMode::Reactive) if windows have focus,
|
||||||
/// [`ReactiveLowPower`](UpdateMode::ReactiveLowPower) otherwise.
|
/// [`ReactiveLowPower`](UpdateMode::ReactiveLowPower) otherwise.
|
||||||
|
///
|
||||||
|
/// Use the [`EventLoopProxy`](crate::EventLoopProxy) to request a redraw from outside bevy.
|
||||||
pub fn desktop_app() -> Self {
|
pub fn desktop_app() -> Self {
|
||||||
WinitSettings {
|
WinitSettings {
|
||||||
focused_mode: UpdateMode::Reactive {
|
focused_mode: UpdateMode::Reactive {
|
||||||
@ -72,6 +74,7 @@ pub enum UpdateMode {
|
|||||||
/// - a redraw has been requested by [`RequestRedraw`](bevy_window::RequestRedraw)
|
/// - a redraw has been requested by [`RequestRedraw`](bevy_window::RequestRedraw)
|
||||||
/// - new [window](`winit::event::WindowEvent`) or [raw input](`winit::event::DeviceEvent`)
|
/// - new [window](`winit::event::WindowEvent`) or [raw input](`winit::event::DeviceEvent`)
|
||||||
/// events have appeared
|
/// events have appeared
|
||||||
|
/// - a redraw has been requested with the [`EventLoopProxy`](crate::EventLoopProxy)
|
||||||
Reactive {
|
Reactive {
|
||||||
/// The approximate time from the start of one update to the next.
|
/// The approximate time from the start of one update to the next.
|
||||||
///
|
///
|
||||||
@ -84,6 +87,7 @@ pub enum UpdateMode {
|
|||||||
/// - `wait` time has elapsed since the previous update
|
/// - `wait` time has elapsed since the previous update
|
||||||
/// - a redraw has been requested by [`RequestRedraw`](bevy_window::RequestRedraw)
|
/// - a redraw has been requested by [`RequestRedraw`](bevy_window::RequestRedraw)
|
||||||
/// - new [window events](`winit::event::WindowEvent`) have appeared
|
/// - 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
|
/// **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).
|
/// don't come from interacting with a window, like [`MouseMotion`](winit::event::DeviceEvent::MouseMotion).
|
||||||
|
@ -39,7 +39,7 @@ impl WinitWindows {
|
|||||||
/// Creates a `winit` window and associates it with our entity.
|
/// Creates a `winit` window and associates it with our entity.
|
||||||
pub fn create_window(
|
pub fn create_window(
|
||||||
&mut self,
|
&mut self,
|
||||||
event_loop: &winit::event_loop::EventLoopWindowTarget<()>,
|
event_loop: &winit::event_loop::EventLoopWindowTarget<crate::UserEvent>,
|
||||||
entity: Entity,
|
entity: Entity,
|
||||||
window: &Window,
|
window: &Window,
|
||||||
adapters: &mut AccessKitAdapters,
|
adapters: &mut AccessKitAdapters,
|
||||||
|
Loading…
Reference in New Issue
Block a user