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"
futures = "0.3.29"
glam = "0.24.1"
paste = "1.0.14"
thiserror = "1.0.51"
tracing = "0.1.40"
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 crate::prelude::*;
use self::path::{InputComponent, UntypedActionPath};
pub trait EntryTrait {
/// Return currently available extensions
fn available_extensions(&self) -> Result<ExtensionSet>;
@@ -52,27 +54,29 @@ pub trait ViewTrait {
pub trait InputTrait {
/// 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.
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.
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.
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.
impl dyn InputTrait {
/// Get the action at the specified path.
pub fn get_action<A: ActionType>(&self, path: ActionPath) -> Result<Action<A>> {
A::get(self, path)
pub fn create_action<P: InputComponent>(
&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
pub trait ActionInputTrait<A> {
fn get(&self) -> A;

View File

@@ -1,7 +1,7 @@
mod graphics;
mod utils;
use std::sync::Mutex;
use std::{rc::Rc, sync::Mutex};
use glam::{Mat4, UVec2};
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(crate) instance: Instance,
// this could definitely be done better
pub(crate) inner_instance: openxr::Instance,
pub(crate) session: openxr::Session<openxr::AnyGraphics>,
pub(crate) action_sets: Mutex<Vec<openxr::ActionSet>>,
pub(crate) render_resources: Mutex<
Option<(
wgpu::Device,
@@ -84,6 +99,7 @@ pub struct OXrSession {
wgpu::Instance,
)>,
>,
pub(crate) bindings: Rc<Mutex<BindingState>>,
pub(crate) frame_state: Mutex<openxr::FrameState>,
pub(crate) views: Mutex<[openxr::View; 2]>,
pub(crate) frame_waiter: Mutex<openxr::FrameWaiter>,
@@ -99,7 +115,6 @@ impl SessionTrait for OXrSession {
fn instance(&self) -> &Instance {
&self.instance
}
fn get_render_resources(
&self,
) -> Option<(
@@ -113,6 +128,10 @@ impl SessionTrait for OXrSession {
}
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!()
}
@@ -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 {
texture: Mutex<Option<wgpu::TextureView>>,
view: openxr::View,
@@ -361,25 +445,3 @@ impl ViewTrait for OXrView {
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(());
}
let mut stream = self.stream.lock().unwrap();
if true {
if should_render {
stream.end(
predicted_display_time,
environment_blend_mode,

View File

@@ -318,6 +318,8 @@ pub fn init_oxr_graphics(
head: session
.create_reference_space(openxr::ReferenceSpaceType::VIEW, openxr::Posef::IDENTITY)?,
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};
impl From<openxr::sys::Result> for XrError {
fn from(value: openxr::sys::Result) -> Self {
fn from(_: openxr::sys::Result) -> Self {
XrError::Placeholder
}
}

View File

@@ -9,12 +9,14 @@ mod api;
pub mod api_traits;
pub mod backend;
pub mod error;
pub mod path;
pub mod types;
pub mod prelude {
pub use super::api::*;
pub use super::api_traits::*;
pub use super::error::*;
pub use super::path::{self, ActionPath};
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, Vec3};
use glam::{Quat, Vec2, Vec3};
use crate::api::Action;
use crate::api_traits::{ActionInputTrait, HapticTrait, InputTrait};
use crate::error::Result;
use crate::path::UntypedActionPath;
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub struct ExtensionSet {
@@ -18,44 +17,6 @@ pub struct SessionCreateInfo {
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 Pose {
@@ -66,37 +27,45 @@ pub struct Pose {
pub trait ActionType: 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 {
type Inner = dyn HapticTrait;
fn get(input: &dyn InputTrait, path: ActionPath) -> Result<Action<Self>> {
input.get_haptics(path)
fn get(input: &dyn InputTrait, name: &str, path: UntypedActionPath) -> Result<Action<Self>> {
input.create_action_haptics(name, path)
}
}
impl ActionType for Pose {
type Inner = dyn ActionInputTrait<Pose>;
fn get(input: &dyn InputTrait, path: ActionPath) -> Result<Action<Self>> {
input.get_pose(path)
fn get(input: &dyn InputTrait, name: &str, path: UntypedActionPath) -> Result<Action<Self>> {
input.create_action_pose(name, path)
}
}
impl ActionType for f32 {
type Inner = dyn ActionInputTrait<f32>;
fn get(input: &dyn InputTrait, path: ActionPath) -> Result<Action<Self>> {
input.get_float(path)
fn get(input: &dyn InputTrait, name: &str, path: UntypedActionPath) -> Result<Action<Self>> {
input.create_action_float(name, path)
}
}
impl ActionType for bool {
type Inner = dyn ActionInputTrait<bool>;
fn get(input: &dyn InputTrait, path: ActionPath) -> Result<Action<Self>> {
input.get_bool(path)
fn get(input: &dyn InputTrait, name: &str, path: UntypedActionPath) -> Result<Action<Self>> {
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)
}
}