mirror of
https://github.com/bevyengine/bevy
synced 2024-11-25 14:10:19 +00:00
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
4 changed files with 24 additions and 8 deletions
|
@ -81,7 +81,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"))]
|
||||
|
@ -240,6 +240,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
|
||||
|
@ -252,7 +261,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
|
||||
|
@ -277,7 +286,7 @@ pub fn winit_runner(mut app: App) {
|
|||
let mut create_window =
|
||||
SystemState::<CreateWindowParams<Added<Window>>>::from_world(&mut app.world);
|
||||
// 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,
|
||||
|
@ -312,8 +321,8 @@ fn handle_winit_event(
|
|||
)>,
|
||||
focused_windows_state: &mut SystemState<(Res<WinitSettings>, Query<&Window>)>,
|
||||
redraw_event_reader: &mut ManualEventReader<RequestRedraw>,
|
||||
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();
|
||||
|
@ -690,6 +699,9 @@ fn handle_winit_event(
|
|||
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,
|
||||
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>,
|
||||
|
|
|
@ -32,7 +32,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,
|
||||
|
|
|
@ -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 {
|
||||
|
@ -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.
|
||||
///
|
||||
|
@ -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).
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in a new issue