api changes

This commit is contained in:
awtterpip
2023-12-27 19:04:21 -06:00
parent ffa9e6d080
commit fd5323069f
8 changed files with 90 additions and 13 deletions

View File

@@ -3,11 +3,14 @@ name = "xr_api"
version = "0.1.0" version = "0.1.0"
edition = "2021" edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [features]
default = ["linked"]
linked = ["openxr/linked"]
[dependencies] [dependencies]
futures = "0.3.29" futures = "0.3.29"
thiserror = "1.0.51" thiserror = "1.0.51"
wgpu = "0.18"
[target.'cfg(not(target_family = "wasm"))'.dependencies] [target.'cfg(not(target_family = "wasm"))'.dependencies]
openxr = "0.17.1" openxr = "0.17.1"

View File

@@ -6,6 +6,12 @@ use crate::prelude::*;
#[derive(Clone)] #[derive(Clone)]
pub struct Entry(Rc<dyn EntryTrait>); pub struct Entry(Rc<dyn EntryTrait>);
impl Entry {
pub fn new() -> Self {
todo!()
}
}
#[derive(Clone)] #[derive(Clone)]
pub struct Instance(Rc<dyn InstanceTrait>); pub struct Instance(Rc<dyn InstanceTrait>);

View File

@@ -1,3 +1,5 @@
use wgpu::{Adapter, AdapterInfo, Device, Queue, TextureView};
use crate::prelude::*; use crate::prelude::*;
pub trait EntryTrait { pub trait EntryTrait {
@@ -19,21 +21,36 @@ pub trait InstanceTrait {
pub trait SessionTrait { pub trait SessionTrait {
/// Returns the [Instance] used to create this. /// Returns the [Instance] used to create this.
fn instance(&self) -> &Instance; fn instance(&self) -> &Instance;
/// Get render resources compatible with this session.
fn get_render_resources(&self)
-> Option<(Device, Queue, AdapterInfo, Adapter, wgpu::Instance)>;
/// Request input modules with the specified bindings. /// Request input modules with the specified bindings.
fn create_input(&self, bindings: Bindings) -> Result<Input>; fn create_input(&self, bindings: Bindings) -> Result<Input>;
/// Blocks until a rendering frame is available and then begins it. /// Blocks until a rendering frame is available, then returns the texture views for the left and right eyes.
fn begin_frame(&self) -> Result<()>; fn begin_frame(&self) -> Result<(TextureView, TextureView)>;
/// Submits rendering work for this frame. /// Submits rendering work for this frame.
fn end_frame(&self) -> Result<()>; fn end_frame(&self) -> Result<()>;
} }
pub trait InputTrait { pub trait InputTrait {
/// Get the haptic action at the specified path.
fn get_haptics(&self, path: ActionId) -> Result<Action<Haptic>>; fn get_haptics(&self, path: ActionId) -> Result<Action<Haptic>>;
/// Get the pose action at the specified path.
fn get_pose(&self, path: ActionId) -> Result<Action<Pose>>; fn get_pose(&self, path: ActionId) -> Result<Action<Pose>>;
/// Get the float action at the specified path.
fn get_float(&self, path: ActionId) -> Result<Action<f32>>; fn get_float(&self, path: ActionId) -> Result<Action<f32>>;
/// Get the boolean action at the specified path.
fn get_bool(&self, path: ActionId) -> Result<Action<bool>>; fn get_bool(&self, path: ActionId) -> Result<Action<bool>>;
} }
// This impl is moved outside of the trait to ensure that InputTrait stays object safe.
impl dyn InputTrait {
/// Get the action at the specified path.
pub fn get_action<A: ActionType>(&self, path: ActionId) -> Result<Action<A>> {
A::get(self, path)
}
}
pub trait ActionTrait { pub trait ActionTrait {
fn id(&self) -> ActionId; fn id(&self) -> ActionId;
} }

View File

@@ -2,6 +2,15 @@ use crate::prelude::*;
pub struct OXrEntry(openxr::Entry); pub struct OXrEntry(openxr::Entry);
impl OXrEntry {
pub fn new() -> Self {
#[cfg(feature = "linked")]
return OXrEntry(openxr::Entry::linked());
#[cfg(not(feature = "linked"))]
return OXrEntry(unsafe { openxr::Entry::load().expect("Failed to load OpenXR runtime") });
}
}
impl EntryTrait for OXrEntry { impl EntryTrait for OXrEntry {
fn available_extensions(&self) -> Result<ExtensionSet> { fn available_extensions(&self) -> Result<ExtensionSet> {
// self.0.enumerate_extensions(); // self.0.enumerate_extensions();

View File

@@ -6,7 +6,8 @@ use std::sync::{
use crate::prelude::*; use crate::prelude::*;
use wasm_bindgen::{closure::Closure, JsCast}; use wasm_bindgen::{closure::Closure, JsCast};
use web_sys::{js_sys, XrFrame, XrInputSource}; use wasm_bindgen_futures::js_sys;
use web_sys::{XrFrame, XrInputSource};
mod utils; mod utils;
@@ -78,7 +79,7 @@ impl SessionTrait for WebXrSession {
.into()) .into())
} }
fn begin_frame(&self) -> Result<()> { fn begin_frame(&self) -> Result<(wgpu::TextureView, wgpu::TextureView)> {
let mut end_frame_sender = self.end_frame_sender.lock().unwrap(); let mut end_frame_sender = self.end_frame_sender.lock().unwrap();
if end_frame_sender.is_some() { if end_frame_sender.is_some() {
Err(XrError::Placeholder)? Err(XrError::Placeholder)?
@@ -87,7 +88,7 @@ impl SessionTrait for WebXrSession {
let (tx_end, rx_end) = channel::<()>(); let (tx_end, rx_end) = channel::<()>();
*end_frame_sender = Some(tx_end); *end_frame_sender = Some(tx_end);
let on_frame: Closure<dyn FnMut(f64, XrFrame)> = let on_frame: Closure<dyn FnMut(f64, XrFrame)> =
Closure::new(move |time: f64, frame: XrFrame| { Closure::new(move |_time: f64, _frame: XrFrame| {
tx.send(()).ok(); tx.send(()).ok();
rx_end.recv().ok(); rx_end.recv().ok();
}); });
@@ -96,7 +97,7 @@ impl SessionTrait for WebXrSession {
.request_animation_frame(on_frame.as_ref().unchecked_ref()); .request_animation_frame(on_frame.as_ref().unchecked_ref());
rx.recv().ok(); rx.recv().ok();
Ok(()) todo!()
} }
fn end_frame(&self) -> Result<()> { fn end_frame(&self) -> Result<()> {
@@ -107,6 +108,18 @@ impl SessionTrait for WebXrSession {
}; };
Ok(()) Ok(())
} }
fn get_render_resources(
&self,
) -> Option<(
wgpu::Device,
wgpu::Queue,
wgpu::AdapterInfo,
wgpu::Adapter,
wgpu::Instance,
)> {
todo!()
}
} }
pub struct WebXrInput { pub struct WebXrInput {

View File

@@ -1,6 +1,6 @@
use wasm_bindgen::JsValue; use wasm_bindgen::JsValue;
use wasm_bindgen_futures::js_sys::Promise;
use wasm_bindgen_futures::JsFuture; use wasm_bindgen_futures::JsFuture;
use web_sys::js_sys::Promise;
pub trait PromiseRes { pub trait PromiseRes {
fn resolve<T: From<JsValue>>(self) -> Result<T, JsValue>; fn resolve<T: From<JsValue>>(self) -> Result<T, JsValue>;

View File

@@ -1,4 +1,11 @@
pub mod api; //! Abstracted API over WebXR and OpenXR
//!
//! This crate is intended to be used as a common API for cross platform projects. It was primarily
//! made for use in Bevy, but can be used elsewhere.
//!
//! To get started, create an [Entry] with [Entry](Entry#method.new)
mod api;
pub mod api_traits; pub mod api_traits;
pub mod backend; pub mod backend;
pub mod error; pub mod error;
@@ -10,3 +17,5 @@ pub mod prelude {
pub use super::error::*; pub use super::error::*;
pub use super::types::*; pub use super::types::*;
} }
pub use api::*;

View File

@@ -1,6 +1,8 @@
use std::rc::Rc; use std::rc::Rc;
use crate::api_traits::{ActionInputTrait, HapticTrait}; use crate::api::Action;
use crate::api_traits::{ActionInputTrait, HapticTrait, InputTrait};
use crate::error::Result;
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)] #[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub struct ExtensionSet {} pub struct ExtensionSet {}
@@ -12,7 +14,7 @@ pub struct Bindings {}
#[derive(Clone, Copy, PartialEq)] #[derive(Clone, Copy, PartialEq)]
pub struct ActionId { pub struct ActionId {
pub handedness: Handedness, pub handedness: Handedness,
pub device: Device, pub device: XrDevice,
} }
#[derive(Clone, Copy, PartialEq)] #[derive(Clone, Copy, PartialEq)]
@@ -23,29 +25,47 @@ pub enum Handedness {
} }
#[derive(Clone, Copy, PartialEq)] #[derive(Clone, Copy, PartialEq)]
pub enum Device { pub enum XrDevice {
Controller, Controller,
} }
pub struct Haptic; pub struct Haptic;
pub struct Pose; pub struct Pose;
pub trait ActionType { pub trait ActionType: Sized {
type Inner; type Inner;
fn get(input: &dyn InputTrait, path: ActionId) -> Result<Action<Self>>;
} }
impl ActionType for Haptic { impl ActionType for Haptic {
type Inner = Rc<dyn HapticTrait>; type Inner = Rc<dyn HapticTrait>;
fn get(input: &dyn InputTrait, path: ActionId) -> Result<Action<Self>> {
input.get_haptics(path)
}
} }
impl ActionType for Pose { impl ActionType for Pose {
type Inner = Rc<dyn ActionInputTrait<Pose>>; type Inner = Rc<dyn ActionInputTrait<Pose>>;
fn get(input: &dyn InputTrait, path: ActionId) -> Result<Action<Self>> {
input.get_pose(path)
}
} }
impl ActionType for f32 { impl ActionType for f32 {
type Inner = Rc<dyn ActionInputTrait<f32>>; type Inner = Rc<dyn ActionInputTrait<f32>>;
fn get(input: &dyn InputTrait, path: ActionId) -> Result<Action<Self>> {
input.get_float(path)
}
} }
impl ActionType for bool { impl ActionType for bool {
type Inner = Rc<dyn ActionInputTrait<bool>>; type Inner = Rc<dyn ActionInputTrait<bool>>;
fn get(input: &dyn InputTrait, path: ActionId) -> Result<Action<Self>> {
input.get_bool(path)
}
} }