path refactor

This commit is contained in:
awtterpip
2024-01-30 19:58:26 -06:00
parent 10825557c6
commit 4678013e1c
9 changed files with 373 additions and 87 deletions

View File

@@ -11,6 +11,7 @@ linked = ["openxr/linked"]
ash = "0.37.3" ash = "0.37.3"
futures = "0.3.29" futures = "0.3.29"
glam = "0.24.1" glam = "0.24.1"
paste = "1.0.14"
thiserror = "1.0.51" thiserror = "1.0.51"
tracing = "0.1.40" tracing = "0.1.40"
wgpu = "0.17.1" wgpu = "0.17.1"

View File

@@ -1,8 +1,10 @@
use glam::UVec2; use glam::{UVec2, Vec2};
use wgpu::{Adapter, AdapterInfo, Device, Queue, TextureView}; use wgpu::{Adapter, AdapterInfo, Device, Queue, TextureView};
use crate::prelude::*; use crate::prelude::*;
use self::path::{InputComponent, UntypedActionPath};
pub trait EntryTrait { pub trait EntryTrait {
/// Return currently available extensions /// Return currently available extensions
fn available_extensions(&self) -> Result<ExtensionSet>; fn available_extensions(&self) -> Result<ExtensionSet>;
@@ -52,27 +54,29 @@ pub trait ViewTrait {
pub trait InputTrait { pub trait InputTrait {
/// Get the haptic action at the specified path. /// Get the haptic action at the specified path.
fn get_haptics(&self, path: ActionPath) -> Result<Action<Haptic>>; fn create_action_haptics(&self, name: &str, path: UntypedActionPath) -> Result<Action<Haptic>>;
/// Get the pose action at the specified path. /// Get the pose action at the specified path.
fn get_pose(&self, path: ActionPath) -> Result<Action<Pose>>; fn create_action_pose(&self, name: &str, path: UntypedActionPath) -> Result<Action<Pose>>;
/// Get the float action at the specified path. /// Get the float action at the specified path.
fn get_float(&self, path: ActionPath) -> Result<Action<f32>>; fn create_action_float(&self, name: &str, path: UntypedActionPath) -> Result<Action<f32>>;
/// Get the boolean action at the specified path. /// Get the boolean action at the specified path.
fn get_bool(&self, path: ActionPath) -> Result<Action<bool>>; fn create_action_bool(&self, name: &str, path: UntypedActionPath) -> Result<Action<bool>>;
/// Get the Vec2 action at the specified path.
fn create_action_vec2(&self, name: &str, path: UntypedActionPath) -> Result<Action<Vec2>>;
} }
// This impl is moved outside of the trait to ensure that InputTrait stays object safe. // This impl is moved outside of the trait to ensure that InputTrait stays object safe.
impl dyn InputTrait { impl dyn InputTrait {
/// Get the action at the specified path. /// Get the action at the specified path.
pub fn get_action<A: ActionType>(&self, path: ActionPath) -> Result<Action<A>> { pub fn create_action<P: InputComponent>(
A::get(self, path) &self,
name: &str,
path: ActionPath<P>,
) -> Result<Action<P::PathType>> {
P::PathType::get(self, name, path.untyped())
} }
} }
pub trait ActionTrait {
fn id(&self) -> ActionPath;
}
/// Represents input actions, such as bools, floats, and poses /// Represents input actions, such as bools, floats, and poses
pub trait ActionInputTrait<A> { pub trait ActionInputTrait<A> {
fn get(&self) -> A; fn get(&self) -> A;

View File

@@ -1,7 +1,7 @@
mod graphics; mod graphics;
mod utils; mod utils;
use std::sync::Mutex; use std::{rc::Rc, sync::Mutex};
use glam::{Mat4, UVec2}; use glam::{Mat4, UVec2};
use openxr::EnvironmentBlendMode; use openxr::EnvironmentBlendMode;
@@ -70,11 +70,26 @@ impl InstanceTrait for OXrInstance {
} }
} }
enum UntypedOXrAction {
Haptics(openxr::Action<openxr::Haptic>),
Pose(openxr::Action<openxr::Posef>),
Float(openxr::Action<f32>),
Bool(openxr::Action<bool>),
Vec2(openxr::Action<openxr::Vector2f>),
}
#[derive(Default)]
struct BindingState {
sets_attached: bool,
bindings: Vec<(UntypedOXrAction, openxr::Path)>,
}
pub struct OXrSession { pub struct OXrSession {
pub(crate) instance: Instance, pub(crate) instance: Instance,
// this could definitely be done better // this could definitely be done better
pub(crate) inner_instance: openxr::Instance, pub(crate) inner_instance: openxr::Instance,
pub(crate) session: openxr::Session<openxr::AnyGraphics>, pub(crate) session: openxr::Session<openxr::AnyGraphics>,
pub(crate) action_sets: Mutex<Vec<openxr::ActionSet>>,
pub(crate) render_resources: Mutex< pub(crate) render_resources: Mutex<
Option<( Option<(
wgpu::Device, wgpu::Device,
@@ -84,6 +99,7 @@ pub struct OXrSession {
wgpu::Instance, wgpu::Instance,
)>, )>,
>, >,
pub(crate) bindings: Rc<Mutex<BindingState>>,
pub(crate) frame_state: Mutex<openxr::FrameState>, pub(crate) frame_state: Mutex<openxr::FrameState>,
pub(crate) views: Mutex<[openxr::View; 2]>, pub(crate) views: Mutex<[openxr::View; 2]>,
pub(crate) frame_waiter: Mutex<openxr::FrameWaiter>, pub(crate) frame_waiter: Mutex<openxr::FrameWaiter>,
@@ -99,7 +115,6 @@ impl SessionTrait for OXrSession {
fn instance(&self) -> &Instance { fn instance(&self) -> &Instance {
&self.instance &self.instance
} }
fn get_render_resources( fn get_render_resources(
&self, &self,
) -> Option<( ) -> Option<(
@@ -113,6 +128,10 @@ impl SessionTrait for OXrSession {
} }
fn create_input(&self, bindings: Bindings) -> Result<Input> { fn create_input(&self, bindings: Bindings) -> Result<Input> {
let action_set = self
.inner_instance
.create_action_set("xr_input", "XR Input", 0)?;
self.action_sets.lock().unwrap().push(action_set.clone());
todo!() todo!()
} }
@@ -239,6 +258,71 @@ impl SessionTrait for OXrSession {
} }
} }
pub struct OXrInput {
inner_instance: openxr::Instance,
action_set: openxr::ActionSet,
bindings: Rc<Mutex<BindingState>>,
}
impl OXrInput {
fn create_action<A: openxr::ActionTy>(
&self,
name: &str,
handed: bool,
) -> openxr::Result<openxr::Action<A>> {
if handed {
let left_path = self.inner_instance.string_to_path("/user/hand/left")?;
let right_path = self.inner_instance.string_to_path("/user/hand/right")?;
self.action_set
.create_action::<A>(name, name, &[left_path, right_path])
} else {
self.action_set.create_action(name, name, &[])
}
}
}
impl InputTrait for OXrInput {
fn create_action_haptics(
&self,
name: &str,
path: path::UntypedActionPath,
) -> Result<Action<Haptic>> {
todo!()
}
fn create_action_pose(
&self,
name: &str,
path: path::UntypedActionPath,
) -> Result<Action<Pose>> {
todo!()
}
fn create_action_float(
&self,
name: &str,
path: path::UntypedActionPath,
) -> Result<Action<f32>> {
todo!()
}
fn create_action_bool(
&self,
name: &str,
path: path::UntypedActionPath,
) -> Result<Action<bool>> {
todo!()
}
fn create_action_vec2(
&self,
name: &str,
path: path::UntypedActionPath,
) -> Result<Action<glam::Vec2>> {
todo!()
}
}
pub struct OXrView { pub struct OXrView {
texture: Mutex<Option<wgpu::TextureView>>, texture: Mutex<Option<wgpu::TextureView>>,
view: openxr::View, view: openxr::View,
@@ -361,25 +445,3 @@ impl ViewTrait for OXrView {
self.format self.format
} }
} }
pub struct OXrInput {
action_set: openxr::ActionSet,
}
impl InputTrait for OXrInput {
fn get_haptics(&self, path: ActionPath) -> Result<Action<Haptic>> {
todo!()
}
fn get_pose(&self, path: ActionPath) -> Result<Action<Pose>> {
todo!()
}
fn get_float(&self, path: ActionPath) -> Result<Action<f32>> {
todo!()
}
fn get_bool(&self, path: ActionPath) -> Result<Action<bool>> {
todo!()
}
}

View File

@@ -149,7 +149,7 @@ impl<G: openxr::Graphics> SwapchainInner<G> {
return Ok(()); return Ok(());
} }
let mut stream = self.stream.lock().unwrap(); let mut stream = self.stream.lock().unwrap();
if true { if should_render {
stream.end( stream.end(
predicted_display_time, predicted_display_time,
environment_blend_mode, environment_blend_mode,

View File

@@ -318,6 +318,8 @@ pub fn init_oxr_graphics(
head: session head: session
.create_reference_space(openxr::ReferenceSpaceType::VIEW, openxr::Posef::IDENTITY)?, .create_reference_space(openxr::ReferenceSpaceType::VIEW, openxr::Posef::IDENTITY)?,
format: swapchain_format, format: swapchain_format,
action_sets: Default::default(),
bindings: Default::default(),
}) })
} }

View File

@@ -4,7 +4,7 @@ use openxr::Posef;
use crate::{error::XrError, prelude::Pose}; use crate::{error::XrError, prelude::Pose};
impl From<openxr::sys::Result> for XrError { impl From<openxr::sys::Result> for XrError {
fn from(value: openxr::sys::Result) -> Self { fn from(_: openxr::sys::Result) -> Self {
XrError::Placeholder XrError::Placeholder
} }
} }

View File

@@ -9,12 +9,14 @@ mod api;
pub mod api_traits; pub mod api_traits;
pub mod backend; pub mod backend;
pub mod error; pub mod error;
pub mod path;
pub mod types; pub mod types;
pub mod prelude { pub mod prelude {
pub use super::api::*; pub use super::api::*;
pub use super::api_traits::*; pub use super::api_traits::*;
pub use super::error::*; pub use super::error::*;
pub use super::path::{self, ActionPath};
pub use super::types::*; pub use super::types::*;
} }

246
xr_api/src/path.rs Normal file
View File

@@ -0,0 +1,246 @@
use std::marker::PhantomData;
use glam::Vec2;
use crate::prelude::ActionType;
pub struct ActionPath<P: InputComponent> {
pub(crate) input: InputId,
pub(crate) comp: PathComponent,
pub(crate) hand: Option<Hand>,
_data: PhantomData<P>,
}
pub struct UntypedActionPath {
pub(crate) input: InputId,
pub(crate) comp: PathComponent,
pub(crate) hand: Option<Hand>,
}
impl<P: InputComponent> From<ActionPath<P>> for UntypedActionPath {
fn from(value: ActionPath<P>) -> Self {
value.untyped()
}
}
impl<P: InputComponent> ActionPath<P> {
const fn new(input: InputId, comp: PathComponent, hand: Option<Hand>) -> Self {
Self {
input,
comp,
hand,
_data: PhantomData,
}
}
pub fn untyped(self) -> UntypedActionPath {
UntypedActionPath {
input: self.input,
comp: self.comp,
hand: self.hand,
}
}
}
pub(crate) enum Hand {
Left,
Right,
}
pub(crate) enum PathComponent {
Click,
Touch,
Value,
Axes,
Pose,
Haptic,
}
pub struct Click;
impl Click {
const COMP: PathComponent = PathComponent::Click;
}
pub struct Touch;
impl Touch {
const COMP: PathComponent = PathComponent::Touch;
}
pub struct Value;
impl Value {
const COMP: PathComponent = PathComponent::Value;
}
pub struct Axes;
impl Axes {
const COMP: PathComponent = PathComponent::Axes;
}
pub struct Pose;
impl Pose {
const COMP: PathComponent = PathComponent::Pose;
}
pub struct Haptic;
impl Haptic {
const COMP: PathComponent = PathComponent::Haptic;
}
pub trait InputComponent {
type PathType: ActionType;
}
impl InputComponent for Click {
type PathType = bool;
}
impl InputComponent for Touch {
type PathType = bool;
}
impl InputComponent for Value {
type PathType = bool;
}
impl InputComponent for Axes {
type PathType = Vec2;
}
impl InputComponent for Pose {
type PathType = crate::types::Pose;
}
impl InputComponent for Haptic {
type PathType = crate::types::Haptic;
}
macro_rules! input_ids {
(
$(#[$id_meta:meta])*
$id:ident;
handed {
$(
$(#[$inner_handed_meta:meta])*
$inner_handed:ident {
$(
$comp_name_handed:ident,
)*
}
)*
}
$(
$(#[$inner_meta:meta])*
$inner:ident {
$(
$comp_name:ident,
)*
}
)*
) => {
$(
#[$id_meta]
)*
paste::paste! {
pub(crate) enum $id {
$(
$inner,
)*
$(
[<$inner_handed Left>],
[<$inner_handed Right>],
)*
}
}
pub mod left {
const LEFT: bool = true;
$(
pub type $inner_handed = super::$inner_handed<LEFT>;
)*
}
pub mod right {
const RIGHT: bool = false;
$(
pub type $inner_handed = super::$inner_handed<RIGHT>;
)*
}
$(
$(
#[$inner_handed_meta]
)*
pub struct $inner_handed<const HAND: bool>;
impl $inner_handed<true> {
paste::paste! {
$(
pub const [<$comp_name_handed:snake:upper>]: ActionPath<$comp_name_handed> = ActionPath::<$comp_name_handed>::new($id::[<$inner_handed Left>], $comp_name_handed::COMP, Some(Hand::Left));
)*
}
}
impl $inner_handed<false> {
paste::paste! {
$(
pub const [<$comp_name_handed:snake:upper>]: ActionPath<$comp_name_handed> = ActionPath::<$comp_name_handed>::new($id::[<$inner_handed Right>], $comp_name_handed::COMP, Some(Hand::Right));
)*
}
}
)*
$(
$(
#[$inner_meta]
)*
pub struct $inner;
impl $inner {
paste::paste! {
$(
pub const [<$comp_name:snake:upper>]: ActionPath<$comp_name> = ActionPath::<$comp_name>::new($id::$inner, $comp_name::COMP, None);
)*
}
}
)*
};
}
input_ids! {
InputId;
handed {
PrimaryButton {
Click,
Touch,
}
SecondaryButton {
Click,
Touch,
}
Select {
Click,
}
Menu {
Click,
}
Thumbstick {
Axes,
Click,
Touch,
}
Trigger {
Touch,
Click,
}
Grip {
Click,
Value,
Pose,
}
}
}

View File

@@ -1,10 +1,9 @@
use std::rc::Rc; use glam::{Quat, Vec2, Vec3};
use glam::{Quat, Vec3};
use crate::api::Action; use crate::api::Action;
use crate::api_traits::{ActionInputTrait, HapticTrait, InputTrait}; use crate::api_traits::{ActionInputTrait, HapticTrait, InputTrait};
use crate::error::Result; use crate::error::Result;
use crate::path::UntypedActionPath;
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)] #[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub struct ExtensionSet { pub struct ExtensionSet {
@@ -18,44 +17,6 @@ pub struct SessionCreateInfo {
pub struct Bindings {} pub struct Bindings {}
/// THIS IS NOT COMPLETE, im not sure how i am going to index actions currently.
#[derive(Clone, Copy, PartialEq)]
pub struct ActionPath {
pub device: DevicePath,
pub subpath: SubPath,
}
#[derive(Clone, Copy, PartialEq)]
pub enum DevicePath {
LeftHand,
RightHand,
Head,
Gamepad,
Treadmill,
}
#[derive(Clone, Copy, PartialEq)]
pub enum SubPath {
A,
B,
X,
Y,
Start,
Home,
End,
Select,
Joystick,
Trigger,
Squeeze,
}
#[derive(Clone, Copy, PartialEq)]
pub enum Handedness {
Left,
Right,
None,
}
pub struct Haptic; pub struct Haptic;
pub struct Pose { pub struct Pose {
@@ -66,37 +27,45 @@ pub struct Pose {
pub trait ActionType: Sized { pub trait ActionType: Sized {
type Inner: ?Sized; type Inner: ?Sized;
fn get(input: &dyn InputTrait, path: ActionPath) -> Result<Action<Self>>; fn get(input: &dyn InputTrait, name: &str, path: UntypedActionPath) -> Result<Action<Self>>;
} }
impl ActionType for Haptic { impl ActionType for Haptic {
type Inner = dyn HapticTrait; type Inner = dyn HapticTrait;
fn get(input: &dyn InputTrait, path: ActionPath) -> Result<Action<Self>> { fn get(input: &dyn InputTrait, name: &str, path: UntypedActionPath) -> Result<Action<Self>> {
input.get_haptics(path) input.create_action_haptics(name, path)
} }
} }
impl ActionType for Pose { impl ActionType for Pose {
type Inner = dyn ActionInputTrait<Pose>; type Inner = dyn ActionInputTrait<Pose>;
fn get(input: &dyn InputTrait, path: ActionPath) -> Result<Action<Self>> { fn get(input: &dyn InputTrait, name: &str, path: UntypedActionPath) -> Result<Action<Self>> {
input.get_pose(path) input.create_action_pose(name, path)
} }
} }
impl ActionType for f32 { impl ActionType for f32 {
type Inner = dyn ActionInputTrait<f32>; type Inner = dyn ActionInputTrait<f32>;
fn get(input: &dyn InputTrait, path: ActionPath) -> Result<Action<Self>> { fn get(input: &dyn InputTrait, name: &str, path: UntypedActionPath) -> Result<Action<Self>> {
input.get_float(path) input.create_action_float(name, path)
} }
} }
impl ActionType for bool { impl ActionType for bool {
type Inner = dyn ActionInputTrait<bool>; type Inner = dyn ActionInputTrait<bool>;
fn get(input: &dyn InputTrait, path: ActionPath) -> Result<Action<Self>> { fn get(input: &dyn InputTrait, name: &str, path: UntypedActionPath) -> Result<Action<Self>> {
input.get_bool(path) input.create_action_bool(name, path)
}
}
impl ActionType for Vec2 {
type Inner = dyn ActionInputTrait<Vec2>;
fn get(input: &dyn InputTrait, name: &str, path: UntypedActionPath) -> Result<Action<Self>> {
input.create_action_vec2(name, path)
} }
} }