diff --git a/xr_api/Cargo.toml b/xr_api/Cargo.toml index 8936b3a..504e789 100644 --- a/xr_api/Cargo.toml +++ b/xr_api/Cargo.toml @@ -3,11 +3,14 @@ name = "xr_api" version = "0.1.0" 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] futures = "0.3.29" thiserror = "1.0.51" +wgpu = "0.18" [target.'cfg(not(target_family = "wasm"))'.dependencies] openxr = "0.17.1" diff --git a/xr_api/src/api.rs b/xr_api/src/api.rs index f25508c..394e0fb 100644 --- a/xr_api/src/api.rs +++ b/xr_api/src/api.rs @@ -6,6 +6,12 @@ use crate::prelude::*; #[derive(Clone)] pub struct Entry(Rc); +impl Entry { + pub fn new() -> Self { + todo!() + } +} + #[derive(Clone)] pub struct Instance(Rc); diff --git a/xr_api/src/api_traits.rs b/xr_api/src/api_traits.rs index 61ee541..14e964b 100644 --- a/xr_api/src/api_traits.rs +++ b/xr_api/src/api_traits.rs @@ -1,3 +1,5 @@ +use wgpu::{Adapter, AdapterInfo, Device, Queue, TextureView}; + use crate::prelude::*; pub trait EntryTrait { @@ -19,21 +21,36 @@ pub trait InstanceTrait { pub trait SessionTrait { /// Returns the [Instance] used to create this. 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. fn create_input(&self, bindings: Bindings) -> Result; - /// Blocks until a rendering frame is available and then begins it. - fn begin_frame(&self) -> Result<()>; + /// Blocks until a rendering frame is available, then returns the texture views for the left and right eyes. + fn begin_frame(&self) -> Result<(TextureView, TextureView)>; /// Submits rendering work for this frame. fn end_frame(&self) -> Result<()>; } pub trait InputTrait { + /// Get the haptic action at the specified path. fn get_haptics(&self, path: ActionId) -> Result>; + /// Get the pose action at the specified path. fn get_pose(&self, path: ActionId) -> Result>; + /// Get the float action at the specified path. fn get_float(&self, path: ActionId) -> Result>; + /// Get the boolean action at the specified path. fn get_bool(&self, path: ActionId) -> Result>; } +// 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(&self, path: ActionId) -> Result> { + A::get(self, path) + } +} + pub trait ActionTrait { fn id(&self) -> ActionId; } diff --git a/xr_api/src/backend/oxr.rs b/xr_api/src/backend/oxr.rs index 93c3fff..9bad4b4 100644 --- a/xr_api/src/backend/oxr.rs +++ b/xr_api/src/backend/oxr.rs @@ -2,6 +2,15 @@ use crate::prelude::*; 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 { fn available_extensions(&self) -> Result { // self.0.enumerate_extensions(); diff --git a/xr_api/src/backend/webxr.rs b/xr_api/src/backend/webxr.rs index 6925393..a57bf88 100644 --- a/xr_api/src/backend/webxr.rs +++ b/xr_api/src/backend/webxr.rs @@ -6,7 +6,8 @@ use std::sync::{ use crate::prelude::*; 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; @@ -78,7 +79,7 @@ impl SessionTrait for WebXrSession { .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(); if end_frame_sender.is_some() { Err(XrError::Placeholder)? @@ -87,7 +88,7 @@ impl SessionTrait for WebXrSession { let (tx_end, rx_end) = channel::<()>(); *end_frame_sender = Some(tx_end); let on_frame: Closure = - Closure::new(move |time: f64, frame: XrFrame| { + Closure::new(move |_time: f64, _frame: XrFrame| { tx.send(()).ok(); rx_end.recv().ok(); }); @@ -96,7 +97,7 @@ impl SessionTrait for WebXrSession { .request_animation_frame(on_frame.as_ref().unchecked_ref()); rx.recv().ok(); - Ok(()) + todo!() } fn end_frame(&self) -> Result<()> { @@ -107,6 +108,18 @@ impl SessionTrait for WebXrSession { }; Ok(()) } + + fn get_render_resources( + &self, + ) -> Option<( + wgpu::Device, + wgpu::Queue, + wgpu::AdapterInfo, + wgpu::Adapter, + wgpu::Instance, + )> { + todo!() + } } pub struct WebXrInput { diff --git a/xr_api/src/backend/webxr/utils.rs b/xr_api/src/backend/webxr/utils.rs index 3a9b15c..fbbe473 100644 --- a/xr_api/src/backend/webxr/utils.rs +++ b/xr_api/src/backend/webxr/utils.rs @@ -1,6 +1,6 @@ use wasm_bindgen::JsValue; +use wasm_bindgen_futures::js_sys::Promise; use wasm_bindgen_futures::JsFuture; -use web_sys::js_sys::Promise; pub trait PromiseRes { fn resolve>(self) -> Result; diff --git a/xr_api/src/lib.rs b/xr_api/src/lib.rs index 49025fa..b6ee74c 100644 --- a/xr_api/src/lib.rs +++ b/xr_api/src/lib.rs @@ -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 backend; pub mod error; @@ -10,3 +17,5 @@ pub mod prelude { pub use super::error::*; pub use super::types::*; } + +pub use api::*; diff --git a/xr_api/src/types.rs b/xr_api/src/types.rs index 432e2f0..988f32f 100644 --- a/xr_api/src/types.rs +++ b/xr_api/src/types.rs @@ -1,6 +1,8 @@ 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)] pub struct ExtensionSet {} @@ -12,7 +14,7 @@ pub struct Bindings {} #[derive(Clone, Copy, PartialEq)] pub struct ActionId { pub handedness: Handedness, - pub device: Device, + pub device: XrDevice, } #[derive(Clone, Copy, PartialEq)] @@ -23,29 +25,47 @@ pub enum Handedness { } #[derive(Clone, Copy, PartialEq)] -pub enum Device { +pub enum XrDevice { Controller, } pub struct Haptic; pub struct Pose; -pub trait ActionType { +pub trait ActionType: Sized { type Inner; + + fn get(input: &dyn InputTrait, path: ActionId) -> Result>; } impl ActionType for Haptic { type Inner = Rc; + + fn get(input: &dyn InputTrait, path: ActionId) -> Result> { + input.get_haptics(path) + } } impl ActionType for Pose { type Inner = Rc>; + + fn get(input: &dyn InputTrait, path: ActionId) -> Result> { + input.get_pose(path) + } } impl ActionType for f32 { type Inner = Rc>; + + fn get(input: &dyn InputTrait, path: ActionId) -> Result> { + input.get_float(path) + } } impl ActionType for bool { type Inner = Rc>; + + fn get(input: &dyn InputTrait, path: ActionId) -> Result> { + input.get_bool(path) + } }