make OxrEvent less unsound

Signed-off-by: Schmarni <marnistromer@gmail.com>
This commit is contained in:
Schmarni
2024-11-30 01:16:17 +01:00
parent 5239700eca
commit bc0c1c472b
4 changed files with 22 additions and 14 deletions

View File

@@ -26,7 +26,8 @@ impl Plugin for OxrOverlayPlugin {
} }
fn handle_overlay_event(event: In<OxrEvent>, mut writer: EventWriter<OxrOverlaySessionEvent>) { fn handle_overlay_event(event: In<OxrEvent>, mut writer: EventWriter<OxrOverlaySessionEvent>) {
if let Event::MainSessionVisibilityChangedEXTX(event) = unsafe { event.get() } { // this unwrap will never panic since we are in a valid scope
if let Event::MainSessionVisibilityChangedEXTX(event) = unsafe { event.get() }.unwrap() {
writer.send(OxrOverlaySessionEvent::MainSessionVisibilityChanged { writer.send(OxrOverlaySessionEvent::MainSessionVisibilityChanged {
visible: event.visible(), visible: event.visible(),
flags: event.flags(), flags: event.flags(),

View File

@@ -18,10 +18,8 @@ use bevy::winit::UpdateMode;
use bevy::winit::WinitSettings; use bevy::winit::WinitSettings;
use bevy_mod_xr::session::*; use bevy_mod_xr::session::*;
use openxr::Event; use openxr::Event;
use openxr::EventDataBuffer;
use crate::error::OxrError; use crate::error::OxrError;
use crate::features::overlay::OxrOverlaySessionEvent;
use crate::graphics::*; use crate::graphics::*;
use crate::resources::*; use crate::resources::*;
use crate::session::OxrSession; use crate::session::OxrSession;
@@ -287,7 +285,8 @@ pub fn handle_events(
mut interaction_profile_changed_event: EventWriter<OxrInteractionProfileChanged>, mut interaction_profile_changed_event: EventWriter<OxrInteractionProfileChanged>,
) { ) {
use openxr::Event::*; use openxr::Event::*;
match unsafe { event.get() } { // this unwrap will never panic since we are in a valid scope
match unsafe { event.get() }.unwrap() {
SessionStateChanged(state) => { SessionStateChanged(state) => {
use openxr::SessionState; use openxr::SessionState;

View File

@@ -9,7 +9,7 @@ use bevy::{
use bevy_mod_xr::session::XrSessionPlugin; use bevy_mod_xr::session::XrSessionPlugin;
use bevy_mod_xr::{camera::XrCameraPlugin, session::XrState}; use bevy_mod_xr::{camera::XrCameraPlugin, session::XrState};
use init::OxrInitPlugin; use init::OxrInitPlugin;
use poll_events::{OxrEventHandlers, OxrEventsPlugin}; use poll_events::OxrEventsPlugin;
use render::OxrRenderPlugin; use render::OxrRenderPlugin;
use resources::OxrInstance; use resources::OxrInstance;
use session::OxrSession; use session::OxrSession;
@@ -30,13 +30,13 @@ pub mod helper_traits;
pub mod init; pub mod init;
pub mod layer_builder; pub mod layer_builder;
pub mod next_chain; pub mod next_chain;
pub mod poll_events;
pub mod reference_space; pub mod reference_space;
pub mod render; pub mod render;
pub mod resources; pub mod resources;
pub mod session; pub mod session;
pub mod spaces; pub mod spaces;
pub mod types; pub mod types;
pub mod poll_events;
/// A [`Condition`](bevy::ecs::schedule::Condition) system that says if the OpenXR session is available. /// A [`Condition`](bevy::ecs::schedule::Condition) system that says if the OpenXR session is available.
pub fn openxr_session_available( pub fn openxr_session_available(

View File

@@ -1,4 +1,4 @@
use std::mem; use std::{cell::RefCell, mem, ops::Deref, rc::Rc};
use bevy::{ecs::system::SystemId, prelude::*}; use bevy::{ecs::system::SystemId, prelude::*};
use bevy_mod_xr::session::{XrFirst, XrHandleEvents}; use bevy_mod_xr::session::{XrFirst, XrHandleEvents};
@@ -27,11 +27,15 @@ pub fn poll_events(world: &mut World) {
.poll_event(&mut buffer) .poll_event(&mut buffer)
.expect("Failed to poll event") .expect("Failed to poll event")
{ {
let event = Rc::new(RefCell::new(Some(event)));
for handler in handlers.handlers.iter() { for handler in handlers.handlers.iter() {
if let Err(err) = world.run_system_with_input::<_, ()>(*handler, OxrEvent::new(event)) { if let Err(err) =
world.run_system_with_input::<_, ()>(*handler, OxrEvent::new(event.clone()))
{
error!("error when running oxr event handler: {err}"); error!("error when running oxr event handler: {err}");
}; };
} }
event.deref().take();
} }
world.insert_resource(handlers); world.insert_resource(handlers);
} }
@@ -44,21 +48,22 @@ pub struct OxrEventHandlers {
pub type OxrEventHandler = SystemId<OxrEvent, ()>; pub type OxrEventHandler = SystemId<OxrEvent, ()>;
pub struct OxrEvent { pub struct OxrEvent {
event: Event<'static>, event: Rc<RefCell<Option<Event<'static>>>>,
} }
impl OxrEvent { impl OxrEvent {
pub(crate) fn new<'a>(event: Event<'a>) -> Self { pub(crate) fn new<'a>(event: Rc<RefCell<Option<Event<'a>>>>) -> Self {
Self { Self {
event: unsafe { mem::transmute::<Event<'a>, Event<'static>>(event) }, event: unsafe { mem::transmute(event) },
} }
} }
/// always returns [Some] if called in a valid scope
/// # Safety /// # Safety
/// The event is only valid for the duration of the poll event callback, /// The event is only valid for the duration of the poll event callback,
/// don't Store the [Event] anywhere!! /// don't Store the [Event] anywhere!!
#[allow(clippy::needless_lifetimes)] #[allow(clippy::needless_lifetimes)]
pub unsafe fn get<'a>(&'a self) -> Event<'a> { pub unsafe fn get<'a>(&'a self) -> Option<Event<'a>> {
self.event self.event.borrow().clone()
} }
} }
pub trait OxrEventHandlerExt { pub trait OxrEventHandlerExt {
@@ -68,7 +73,10 @@ pub trait OxrEventHandlerExt {
) -> &mut Self; ) -> &mut Self;
} }
impl OxrEventHandlerExt for App { impl OxrEventHandlerExt for App {
fn add_oxr_event_handler<M>(&mut self, system: impl IntoSystem<OxrEvent, (), M> + 'static) -> &mut Self { fn add_oxr_event_handler<M>(
&mut self,
system: impl IntoSystem<OxrEvent, (), M> + 'static,
) -> &mut Self {
self.init_resource::<OxrEventHandlers>(); self.init_resource::<OxrEventHandlers>();
let id = self.register_system(system); let id = self.register_system(system);
self.world_mut() self.world_mut()