Merge pull request #183 from Schmarni-Dev/better_oxr_events
make OpenXR event handlers completely safe! (no unsafe!)
This commit is contained in:
@@ -7,7 +7,7 @@ use crate::{
|
||||
next_chain::{OxrNextChainStructBase, OxrNextChainStructProvider},
|
||||
openxr::exts::OxrEnabledExtensions,
|
||||
openxr_session_available,
|
||||
poll_events::{OxrEvent, OxrEventHandlerExt},
|
||||
poll_events::{OxrEventHandlerExt, OxrEventIn},
|
||||
session::{OxrSessionCreateNextChain, OxrSessionCreateNextProvider},
|
||||
};
|
||||
|
||||
@@ -25,9 +25,8 @@ impl Plugin for OxrOverlayPlugin {
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_overlay_event(event: In<OxrEvent>, mut writer: EventWriter<OxrOverlaySessionEvent>) {
|
||||
// this unwrap will never panic since we are in a valid scope
|
||||
if let Event::MainSessionVisibilityChangedEXTX(event) = unsafe { event.get() }.unwrap() {
|
||||
fn handle_overlay_event(event: OxrEventIn, mut writer: EventWriter<OxrOverlaySessionEvent>) {
|
||||
if let Event::MainSessionVisibilityChangedEXTX(event) = *event {
|
||||
writer.send(OxrOverlaySessionEvent::MainSessionVisibilityChanged {
|
||||
visible: event.visible(),
|
||||
flags: event.flags(),
|
||||
|
||||
@@ -27,7 +27,7 @@ use crate::session::OxrSessionCreateNextChain;
|
||||
use crate::types::*;
|
||||
|
||||
use super::exts::OxrEnabledExtensions;
|
||||
use super::poll_events::OxrEvent;
|
||||
use super::poll_events::OxrEventIn;
|
||||
use super::poll_events::OxrEventHandlerExt;
|
||||
|
||||
pub fn session_started(started: Option<Res<OxrSessionStarted>>) -> bool {
|
||||
@@ -297,14 +297,13 @@ impl OxrInitPlugin {
|
||||
pub struct OxrInteractionProfileChanged;
|
||||
|
||||
pub fn handle_events(
|
||||
event: In<OxrEvent>,
|
||||
event: OxrEventIn,
|
||||
mut status: ResMut<XrState>,
|
||||
mut changed_event: EventWriter<XrStateChanged>,
|
||||
mut interaction_profile_changed_event: EventWriter<OxrInteractionProfileChanged>,
|
||||
) {
|
||||
use openxr::Event::*;
|
||||
// this unwrap will never panic since we are in a valid scope
|
||||
match unsafe { event.get() }.unwrap() {
|
||||
match *event {
|
||||
SessionStateChanged(state) => {
|
||||
use openxr::SessionState;
|
||||
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
use std::{cell::RefCell, mem, ops::Deref, rc::Rc};
|
||||
|
||||
use bevy::{ecs::system::SystemId, prelude::*};
|
||||
use bevy_mod_xr::session::{XrFirst, XrHandleEvents};
|
||||
use openxr::{Event, EventDataBuffer};
|
||||
@@ -27,63 +25,51 @@ pub fn poll_events(world: &mut World) {
|
||||
.poll_event(&mut buffer)
|
||||
.expect("Failed to poll event")
|
||||
{
|
||||
let event = Rc::new(RefCell::new(Some(event)));
|
||||
for handler in handlers.handlers.iter() {
|
||||
if let Err(err) =
|
||||
world.run_system_with_input::<_, ()>(*handler, OxrEvent::new(event.clone()))
|
||||
for handler in handlers
|
||||
.0
|
||||
.iter()
|
||||
.map(|v| SystemId::<OxrEventIn, ()>::from_entity(*v))
|
||||
{
|
||||
if let Err(err) = world.run_system_with_input(handler, event) {
|
||||
error!("error when running oxr event handler: {err}");
|
||||
};
|
||||
}
|
||||
event.deref().take();
|
||||
}
|
||||
world.insert_resource(handlers);
|
||||
}
|
||||
|
||||
use super::{openxr_session_available, resources::OxrInstance};
|
||||
#[derive(Resource, Debug, Default)]
|
||||
pub struct OxrEventHandlers {
|
||||
pub handlers: Vec<OxrEventHandler>,
|
||||
}
|
||||
pub type OxrEventHandler = SystemId<In<OxrEvent>, ()>;
|
||||
|
||||
pub struct OxrEvent {
|
||||
event: Rc<RefCell<Option<Event<'static>>>>,
|
||||
}
|
||||
|
||||
impl OxrEvent {
|
||||
pub(crate) fn new(event: Rc<RefCell<Option<Event<'_>>>>) -> Self {
|
||||
Self {
|
||||
#[allow(clippy::missing_transmute_annotations)]
|
||||
event: unsafe { mem::transmute(event) },
|
||||
}
|
||||
}
|
||||
/// always returns [Some] if called in a valid scope
|
||||
/// # Safety
|
||||
/// The event is only valid for the duration of the poll event callback,
|
||||
/// don't Store the [Event] anywhere!!
|
||||
#[allow(clippy::needless_lifetimes)]
|
||||
pub unsafe fn get<'a>(&'a self) -> Option<Event<'a>> {
|
||||
*self.event.borrow()
|
||||
}
|
||||
}
|
||||
pub struct OxrEventHandlers(Vec<Entity>);
|
||||
pub trait OxrEventHandlerExt {
|
||||
fn add_oxr_event_handler<M>(
|
||||
&mut self,
|
||||
system: impl IntoSystem<In<OxrEvent>, (), M> + 'static,
|
||||
system: impl IntoSystem<OxrEventIn<'static>, (), M> + 'static,
|
||||
) -> &mut Self;
|
||||
}
|
||||
impl OxrEventHandlerExt for App {
|
||||
fn add_oxr_event_handler<M>(
|
||||
&mut self,
|
||||
system: impl IntoSystem<In<OxrEvent>, (), M> + 'static,
|
||||
system: impl IntoSystem<OxrEventIn<'static>, (), M> + 'static,
|
||||
) -> &mut Self {
|
||||
self.init_resource::<OxrEventHandlers>();
|
||||
let id = self.register_system(system);
|
||||
self.world_mut()
|
||||
.resource_mut::<OxrEventHandlers>()
|
||||
.handlers
|
||||
.push(id);
|
||||
.0
|
||||
.push(id.entity());
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Deref)]
|
||||
pub struct OxrEventIn<'a>(pub Event<'a>);
|
||||
impl SystemInput for OxrEventIn<'_> {
|
||||
type Param<'i> = OxrEventIn<'i>;
|
||||
|
||||
type Inner<'i> = Event<'i>;
|
||||
|
||||
fn wrap(this: Self::Inner<'_>) -> Self::Param<'_> {
|
||||
OxrEventIn(this)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user