mirror of
https://github.com/bevyengine/bevy
synced 2024-11-10 07:04:33 +00:00
Remove need for EventLoopProxy to be NonSend (#14198)
# Objective - Continue to pare down the uses on NonSend resources in the engine. In this case, EventLoopProxy used to be `!Sync`, but is now `Sync` in the latest version of winit. ## Solution - New type `EventLoopProxy` as `EventLoopProxyWrapper` to make it into a normal resource. - Update the `custom_user_event` example as it no longer needs to indirectly access the `EventLoopProxy` through a static variable anymore. ## Testing - Ran the example. The resource exists just for users to use, so there aren't any in engine uses for it currently. --- ## Changelog - make EventLoopProxy into a regular resource. ## Migration Guide `EventLoopProxy` has been renamed to `EventLoopProxyWrapper` and is now `Send`, making it an ordinary resource. Before: ```rust event_loop_system(event_loop: NonSend<EventLoopProxy<MyEvent>>) { event_loop.send_event(MyEvent); } ``` After: ```rust event_loop_system(event_loop: Res<EventLoopProxy<MyEvent>>) { event_loop.send_event(MyEvent); } ```
This commit is contained in:
parent
1042f09c2e
commit
cfcb56f5b9
4 changed files with 29 additions and 35 deletions
|
@ -12,6 +12,7 @@
|
|||
//! The app's [runner](bevy_app::App::runner) is set by `WinitPlugin` and handles the `winit` [`EventLoop`].
|
||||
//! See `winit_runner` for details.
|
||||
|
||||
use bevy_derive::Deref;
|
||||
use bevy_window::RawHandleWrapperHolder;
|
||||
use std::marker::PhantomData;
|
||||
use winit::event_loop::EventLoop;
|
||||
|
@ -25,6 +26,7 @@ use bevy_ecs::prelude::*;
|
|||
use bevy_window::{exit_on_all_closed, Window, WindowCreated};
|
||||
pub use system::create_windows;
|
||||
use system::{changed_windows, despawn_windows};
|
||||
pub use winit::event_loop::EventLoopProxy;
|
||||
pub use winit_config::*;
|
||||
pub use winit_event::*;
|
||||
pub use winit_windows::*;
|
||||
|
@ -142,12 +144,14 @@ impl<T: Event> Plugin for WinitPlugin<T> {
|
|||
#[derive(Debug, Default, Clone, Copy, Event)]
|
||||
pub struct WakeUp;
|
||||
|
||||
/// A re-export of [`winit::event_loop::EventLoopProxy`].
|
||||
/// A wrapper type around [`winit::event_loop::EventLoopProxy`] with the specific
|
||||
/// [`winit::event::Event::UserEvent`] used in the [`WinitPlugin`].
|
||||
///
|
||||
/// The `EventLoopProxy` can be used to request a redraw from outside bevy.
|
||||
///
|
||||
/// Use `NonSend<EventLoopProxy>` to receive this resource.
|
||||
pub type EventLoopProxy<T> = winit::event_loop::EventLoopProxy<T>;
|
||||
/// Use `Res<EventLoopProxy>` to receive this resource.
|
||||
#[derive(Resource, Deref)]
|
||||
pub struct EventLoopProxyWrapper<T: 'static>(winit::event_loop::EventLoopProxy<T>);
|
||||
|
||||
trait AppSendEvent {
|
||||
fn send(&mut self, event: impl Into<WinitEvent>);
|
||||
|
|
|
@ -37,8 +37,8 @@ use bevy_window::{PrimaryWindow, RawHandleWrapper};
|
|||
use crate::accessibility::AccessKitAdapters;
|
||||
use crate::system::CachedWindow;
|
||||
use crate::{
|
||||
converters, create_windows, AppSendEvent, CreateWindowParams, UpdateMode, WinitEvent,
|
||||
WinitSettings, WinitWindows,
|
||||
converters, create_windows, AppSendEvent, CreateWindowParams, EventLoopProxyWrapper,
|
||||
UpdateMode, WinitEvent, WinitSettings, WinitWindows,
|
||||
};
|
||||
|
||||
/// Persistent state that is used to run the [`App`] according to the current
|
||||
|
@ -763,7 +763,7 @@ pub fn winit_runner<T: Event>(mut app: App) -> AppExit {
|
|||
.unwrap();
|
||||
|
||||
app.world_mut()
|
||||
.insert_non_send_resource(event_loop.create_proxy());
|
||||
.insert_resource(EventLoopProxyWrapper(event_loop.create_proxy()));
|
||||
|
||||
let mut runner_state = WinitAppRunnerState::new(app);
|
||||
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
//! Shows how to create a custom event that can be handled by `winit`'s event loop.
|
||||
|
||||
use bevy::prelude::*;
|
||||
use bevy::winit::{EventLoopProxy, WakeUp, WinitPlugin};
|
||||
use bevy::winit::{EventLoopProxyWrapper, WakeUp, WinitPlugin};
|
||||
use std::fmt::Formatter;
|
||||
use std::sync::OnceLock;
|
||||
|
||||
#[derive(Default, Debug, Event)]
|
||||
enum CustomEvent {
|
||||
|
@ -21,8 +20,6 @@ impl std::fmt::Display for CustomEvent {
|
|||
}
|
||||
}
|
||||
|
||||
static EVENT_LOOP_PROXY: OnceLock<EventLoopProxy<CustomEvent>> = OnceLock::new();
|
||||
|
||||
fn main() {
|
||||
let winit_plugin = WinitPlugin::<CustomEvent>::default();
|
||||
|
||||
|
@ -39,7 +36,6 @@ fn main() {
|
|||
Startup,
|
||||
(
|
||||
setup,
|
||||
expose_event_loop_proxy,
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
wasm::setup_js_closure,
|
||||
),
|
||||
|
@ -52,11 +48,10 @@ fn setup(mut commands: Commands) {
|
|||
commands.spawn(Camera2dBundle::default());
|
||||
}
|
||||
|
||||
fn send_event(input: Res<ButtonInput<KeyCode>>) {
|
||||
let Some(event_loop_proxy) = EVENT_LOOP_PROXY.get() else {
|
||||
return;
|
||||
};
|
||||
|
||||
fn send_event(
|
||||
input: Res<ButtonInput<KeyCode>>,
|
||||
event_loop_proxy: Res<EventLoopProxyWrapper<CustomEvent>>,
|
||||
) {
|
||||
if input.just_pressed(KeyCode::Space) {
|
||||
let _ = event_loop_proxy.send_event(CustomEvent::WakeUp);
|
||||
}
|
||||
|
@ -64,18 +59,15 @@ fn send_event(input: Res<ButtonInput<KeyCode>>) {
|
|||
// This simulates sending a custom event through an external thread.
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
if input.just_pressed(KeyCode::KeyE) {
|
||||
let handler = std::thread::spawn(|| {
|
||||
let _ = event_loop_proxy.send_event(CustomEvent::Key('e'));
|
||||
let event_loop_proxy = event_loop_proxy.clone();
|
||||
let handler = std::thread::spawn(move || {
|
||||
let _ = event_loop_proxy.clone().send_event(CustomEvent::Key('e'));
|
||||
});
|
||||
|
||||
handler.join().unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
fn expose_event_loop_proxy(event_loop_proxy: NonSend<EventLoopProxy<CustomEvent>>) {
|
||||
EVENT_LOOP_PROXY.set((*event_loop_proxy).clone()).unwrap();
|
||||
}
|
||||
|
||||
fn handle_event(mut events: EventReader<CustomEvent>) {
|
||||
for evt in events.read() {
|
||||
info!("Received event: {evt:?}");
|
||||
|
@ -87,19 +79,21 @@ fn handle_event(mut events: EventReader<CustomEvent>) {
|
|||
/// the loop if that's currently waiting for a timeout or a user event.
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
pub(crate) mod wasm {
|
||||
use crate::{CustomEvent, EVENT_LOOP_PROXY};
|
||||
use super::*;
|
||||
use bevy::winit::EventLoopProxy;
|
||||
use wasm_bindgen::prelude::*;
|
||||
use wasm_bindgen::JsCast;
|
||||
use web_sys::KeyboardEvent;
|
||||
|
||||
pub(crate) fn setup_js_closure() {
|
||||
pub(crate) fn setup_js_closure(event_loop: Res<EventLoopProxyWrapper<CustomEvent>>) {
|
||||
let window = web_sys::window().unwrap();
|
||||
let document = window.document().unwrap();
|
||||
|
||||
let event_loop = event_loop.clone();
|
||||
let closure = Closure::wrap(Box::new(move |event: KeyboardEvent| {
|
||||
let key = event.key();
|
||||
if key == "e" {
|
||||
send_custom_event('e').unwrap();
|
||||
send_custom_event('e', &event_loop).unwrap();
|
||||
}
|
||||
}) as Box<dyn FnMut(KeyboardEvent)>);
|
||||
|
||||
|
@ -110,13 +104,9 @@ pub(crate) mod wasm {
|
|||
closure.forget();
|
||||
}
|
||||
|
||||
fn send_custom_event(ch: char) -> Result<(), String> {
|
||||
if let Some(proxy) = EVENT_LOOP_PROXY.get() {
|
||||
fn send_custom_event(ch: char, proxy: &EventLoopProxy<CustomEvent>) -> Result<(), String> {
|
||||
proxy
|
||||
.send_event(CustomEvent::Key(ch))
|
||||
.map_err(|_| "Failed to send event".to_string())
|
||||
} else {
|
||||
Err("Event loop proxy not found".to_string())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ use bevy::{
|
|||
prelude::*,
|
||||
utils::Duration,
|
||||
window::{PresentMode, RequestRedraw, WindowPlugin},
|
||||
winit::{EventLoopProxy, WakeUp, WinitSettings},
|
||||
winit::{EventLoopProxyWrapper, WakeUp, WinitSettings},
|
||||
};
|
||||
|
||||
fn main() {
|
||||
|
@ -55,7 +55,7 @@ enum ExampleMode {
|
|||
fn update_winit(
|
||||
mode: Res<ExampleMode>,
|
||||
mut winit_config: ResMut<WinitSettings>,
|
||||
event_loop_proxy: NonSend<EventLoopProxy<WakeUp>>,
|
||||
event_loop_proxy: Res<EventLoopProxyWrapper<WakeUp>>,
|
||||
mut redraw_request_events: EventWriter<RequestRedraw>,
|
||||
) {
|
||||
use ExampleMode::*;
|
||||
|
|
Loading…
Reference in a new issue