path refactor
This commit is contained in:
@@ -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"
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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!()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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(),
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
246
xr_api/src/path.rs
Normal 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,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user