make OpenXR event handlers completely safe! (no more unsafe at all in there)
Signed-off-by: Schmarni <marnistromer@gmail.com>
This commit is contained in:
@@ -7,7 +7,7 @@ use crate::{
|
|||||||
next_chain::{OxrNextChainStructBase, OxrNextChainStructProvider},
|
next_chain::{OxrNextChainStructBase, OxrNextChainStructProvider},
|
||||||
openxr::exts::OxrEnabledExtensions,
|
openxr::exts::OxrEnabledExtensions,
|
||||||
openxr_session_available,
|
openxr_session_available,
|
||||||
poll_events::{OxrEvent, OxrEventHandlerExt},
|
poll_events::{OxrEventHandlerExt, OxrEventIn},
|
||||||
session::{OxrSessionCreateNextChain, OxrSessionCreateNextProvider},
|
session::{OxrSessionCreateNextChain, OxrSessionCreateNextProvider},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -25,9 +25,8 @@ impl Plugin for OxrOverlayPlugin {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_overlay_event(event: In<OxrEvent>, mut writer: EventWriter<OxrOverlaySessionEvent>) {
|
fn handle_overlay_event(event: OxrEventIn, mut writer: EventWriter<OxrOverlaySessionEvent>) {
|
||||||
// this unwrap will never panic since we are in a valid scope
|
if let Event::MainSessionVisibilityChangedEXTX(event) = *event {
|
||||||
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(),
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ use crate::session::OxrSessionCreateNextChain;
|
|||||||
use crate::types::*;
|
use crate::types::*;
|
||||||
|
|
||||||
use super::exts::OxrEnabledExtensions;
|
use super::exts::OxrEnabledExtensions;
|
||||||
use super::poll_events::OxrEvent;
|
use super::poll_events::OxrEventIn;
|
||||||
use super::poll_events::OxrEventHandlerExt;
|
use super::poll_events::OxrEventHandlerExt;
|
||||||
|
|
||||||
pub fn session_started(started: Option<Res<OxrSessionStarted>>) -> bool {
|
pub fn session_started(started: Option<Res<OxrSessionStarted>>) -> bool {
|
||||||
@@ -297,14 +297,13 @@ impl OxrInitPlugin {
|
|||||||
pub struct OxrInteractionProfileChanged;
|
pub struct OxrInteractionProfileChanged;
|
||||||
|
|
||||||
pub fn handle_events(
|
pub fn handle_events(
|
||||||
event: In<OxrEvent>,
|
event: OxrEventIn,
|
||||||
mut status: ResMut<XrState>,
|
mut status: ResMut<XrState>,
|
||||||
mut changed_event: EventWriter<XrStateChanged>,
|
mut changed_event: EventWriter<XrStateChanged>,
|
||||||
mut interaction_profile_changed_event: EventWriter<OxrInteractionProfileChanged>,
|
mut interaction_profile_changed_event: EventWriter<OxrInteractionProfileChanged>,
|
||||||
) {
|
) {
|
||||||
use openxr::Event::*;
|
use openxr::Event::*;
|
||||||
// this unwrap will never panic since we are in a valid scope
|
match *event {
|
||||||
match unsafe { event.get() }.unwrap() {
|
|
||||||
SessionStateChanged(state) => {
|
SessionStateChanged(state) => {
|
||||||
use openxr::SessionState;
|
use openxr::SessionState;
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
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};
|
||||||
use openxr::{Event, EventDataBuffer};
|
use openxr::{Event, EventDataBuffer};
|
||||||
@@ -27,63 +25,51 @@ 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
|
||||||
for handler in handlers.handlers.iter() {
|
.0
|
||||||
if let Err(err) =
|
.iter()
|
||||||
world.run_system_with_input::<_, ()>(*handler, OxrEvent::new(event.clone()))
|
.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}");
|
error!("error when running oxr event handler: {err}");
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
event.deref().take();
|
|
||||||
}
|
}
|
||||||
world.insert_resource(handlers);
|
world.insert_resource(handlers);
|
||||||
}
|
}
|
||||||
|
|
||||||
use super::{openxr_session_available, resources::OxrInstance};
|
use super::{openxr_session_available, resources::OxrInstance};
|
||||||
#[derive(Resource, Debug, Default)]
|
#[derive(Resource, Debug, Default)]
|
||||||
pub struct OxrEventHandlers {
|
pub struct OxrEventHandlers(Vec<Entity>);
|
||||||
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 trait OxrEventHandlerExt {
|
pub trait OxrEventHandlerExt {
|
||||||
fn add_oxr_event_handler<M>(
|
fn add_oxr_event_handler<M>(
|
||||||
&mut self,
|
&mut self,
|
||||||
system: impl IntoSystem<In<OxrEvent>, (), M> + 'static,
|
system: impl IntoSystem<OxrEventIn<'static>, (), M> + 'static,
|
||||||
) -> &mut Self;
|
) -> &mut Self;
|
||||||
}
|
}
|
||||||
impl OxrEventHandlerExt for App {
|
impl OxrEventHandlerExt for App {
|
||||||
fn add_oxr_event_handler<M>(
|
fn add_oxr_event_handler<M>(
|
||||||
&mut self,
|
&mut self,
|
||||||
system: impl IntoSystem<In<OxrEvent>, (), M> + 'static,
|
system: impl IntoSystem<OxrEventIn<'static>, (), M> + 'static,
|
||||||
) -> &mut Self {
|
) -> &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()
|
||||||
.resource_mut::<OxrEventHandlers>()
|
.resource_mut::<OxrEventHandlers>()
|
||||||
.handlers
|
.0
|
||||||
.push(id);
|
.push(id.entity());
|
||||||
self
|
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