Skip to content

Commit

Permalink
add support for Vec2 Actions, slightly changed the way actions are cr…
Browse files Browse the repository at this point in the history
…eated but no functionality change and changed the get_action_* return result to a custom error
  • Loading branch information
Schmarni-Dev committed Dec 12, 2023
1 parent 2e492e1 commit d84d02a
Showing 1 changed file with 99 additions and 56 deletions.
155 changes: 99 additions & 56 deletions src/xr_input/actions.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
use std::error::Error;

use bevy::{prelude::*, utils::HashMap};
use openxr as xr;
use xr::{Action, Binding, Haptic, Posef};
use xr::{Action, Binding, Haptic, Posef, Vector2f};

use crate::{resources::{XrInstance, XrSession}, xr_init::XrPrePostSetup};
use crate::{
resources::{XrInstance, XrSession},
xr_init::XrPrePostSetup,
};

use super::oculus_touch::ActionSets;

Expand All @@ -16,6 +21,22 @@ impl Plugin for OpenXrActionsPlugin {
}
}

#[inline(always)]
fn create_action<T: xr::ActionTy>(
action: &SetupAction,
action_name: &'static str,
oxr_action_set: &xr::ActionSet,
hands: &[xr::Path],
) -> xr::Action<T> {
match action.handednes {
ActionHandednes::Single => oxr_action_set
.create_action(action_name, &action.pretty_name, &[])
.unwrap_or_else(|_| panic!("Unable to create action: {}", action_name)),
ActionHandednes::Double => oxr_action_set
.create_action(action_name, &action.pretty_name, hands)
.unwrap_or_else(|_| panic!("Unable to create action: {}", action_name)),
}
}
pub fn setup_oxr_actions(world: &mut World) {
let actions = world.remove_resource::<SetupActionSets>().unwrap();
let instance = world.get_resource::<XrInstance>().unwrap();
Expand All @@ -27,50 +48,33 @@ pub fn setup_oxr_actions(world: &mut World) {
let mut oxr_action_sets = Vec::new();
let mut action_sets = XrActionSets { sets: default() };
// let mut action_bindings: HashMap<&'static str, Vec<xr::Path>> = HashMap::new();
let mut a_iter = actions.sets.into_iter();
let mut action_bindings: HashMap<
(&'static str, &'static str),
HashMap<&'static str, Vec<xr::Path>>,
> = HashMap::new();
while let Some((set_name, set)) = a_iter.next() {
for (set_name, set) in actions.sets.into_iter() {
let mut actions: HashMap<&'static str, TypedAction> = default();
let oxr_action_set = instance
.create_action_set(set_name, &set.pretty_name, set.priority)
.expect("Unable to create action set");
for (action_name, action) in set.actions.into_iter() {
use self::create_action as ca;
let typed_action = match action.action_type {
ActionType::F32 => TypedAction::F32(match action.handednes {
ActionHandednes::Single => oxr_action_set
.create_action(action_name, &action.pretty_name, &[])
.expect(&format!("Unable to create action: {}", action_name)),
ActionHandednes::Double => oxr_action_set
.create_action(action_name, &action.pretty_name, &hands)
.expect(&format!("Unable to create action: {}", action_name)),
}),
ActionType::Bool => TypedAction::Bool(match action.handednes {
ActionHandednes::Single => oxr_action_set
.create_action(action_name, &action.pretty_name, &[])
.expect(&format!("Unable to create action: {}", action_name)),
ActionHandednes::Double => oxr_action_set
.create_action(action_name, &action.pretty_name, &hands)
.expect(&format!("Unable to create action: {}", action_name)),
}),
ActionType::PoseF => TypedAction::PoseF(match action.handednes {
ActionHandednes::Single => oxr_action_set
.create_action(action_name, &action.pretty_name, &[])
.expect(&format!("Unable to create action: {}", action_name)),
ActionHandednes::Double => oxr_action_set
.create_action(action_name, &action.pretty_name, &hands)
.expect(&format!("Unable to create action: {}", action_name)),
}),
ActionType::Haptic => TypedAction::Haptic(match action.handednes {
ActionHandednes::Single => oxr_action_set
.create_action(action_name, &action.pretty_name, &[])
.expect(&format!("Unable to create action: {}", action_name)),
ActionHandednes::Double => oxr_action_set
.create_action(action_name, &action.pretty_name, &hands)
.expect(&format!("Unable to create action: {}", action_name)),
}),
ActionType::Vec2 => {
TypedAction::Vec2(ca(&action, action_name, &oxr_action_set, &hands))
}
ActionType::F32 => {
TypedAction::F32(ca(&action, action_name, &oxr_action_set, &hands))
}
ActionType::Bool => {
TypedAction::Bool(ca(&action, action_name, &oxr_action_set, &hands))
}
ActionType::PoseF => {
TypedAction::PoseF(ca(&action, action_name, &oxr_action_set, &hands))
}
ActionType::Haptic => {
TypedAction::Haptic(ca(&action, action_name, &oxr_action_set, &hands))
}
};
actions.insert(action_name, typed_action);
for (device_path, bindings) in action.bindings.into_iter() {
Expand Down Expand Up @@ -107,18 +111,19 @@ pub fn setup_oxr_actions(world: &mut World) {
.zip([&action_bindings].into_iter().cycle())
.flat_map(move |((set_name, action_name, action), bindings)| {
bindings
.get(&(set_name.clone(), action_name.clone()))
.get(&(set_name as &'static str, action_name as &'static str))
.unwrap()
.iter()
.map(move |(dev, bindings)| (action.clone(), dev.clone(), bindings))
.map(move |(dev, bindings)| (action, dev, bindings))
})
.map(|(action, dev, bindings)| {
info!("Hi");
(
dev,
bindings
.into_iter()
.iter()
.map(move |binding| match &action {
TypedAction::Vec2(a) => Binding::new(a, *binding),
TypedAction::F32(a) => Binding::new(a, *binding),
TypedAction::Bool(a) => Binding::new(a, *binding),
TypedAction::PoseF(a) => Binding::new(a, *binding),
Expand Down Expand Up @@ -155,13 +160,15 @@ pub enum ActionType {
Bool,
PoseF,
Haptic,
Vec2,
}

pub enum TypedAction {
F32(Action<f32>),
Bool(Action<bool>),
PoseF(Action<Posef>),
Haptic(Action<Haptic>),
Vec2(Action<Vector2f>),
}

pub struct SetupAction {
Expand Down Expand Up @@ -247,7 +254,7 @@ impl SetupActionSets {
}

pub struct ActionSet {
// oxr_action_set: xr::ActionSet,
// add functionality to enable/disable action sets
enabled: bool,
actions: HashMap<&'static str, TypedAction>,
}
Expand All @@ -257,73 +264,109 @@ pub struct XrActionSets {
sets: HashMap<&'static str, ActionSet>,
}

use std::fmt::Display as FmtDisplay;
impl FmtDisplay for ActionError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let err = match self {
ActionError::NoActionSet => "Action Set Not Found!",
ActionError::NoAction => "Action Not Found!",
ActionError::WrongActionType => "Wrong Action Type!",
};
write!(f, "{}", err)
}
}
impl Error for ActionError {}
#[derive(Debug)]
pub enum ActionError {
NoActionSet,
NoAction,
WrongActionType,
}

impl XrActionSets {
pub fn get_action_vec2(
&self,
action_set: &'static str,
action_name: &'static str,
) -> Result<&Action<Vector2f>, ActionError> {
let action = self
.sets
.get(action_set)
.ok_or(ActionError::NoActionSet)?
.actions
.get(action_name)
.ok_or(ActionError::NoAction)?;
match action {
TypedAction::Vec2(a) => Ok(a),
_ => Err(ActionError::WrongActionType),
}
}
pub fn get_action_f32(
&self,
action_set: &'static str,
action_name: &'static str,
) -> anyhow::Result<&Action<f32>> {
) -> Result<&Action<f32>,ActionError> {
let action = self
.sets
.get(action_set)
.ok_or(anyhow::anyhow!("Action Set Not Found!"))?
.ok_or(ActionError::NoActionSet)?
.actions
.get(action_name)
.ok_or(anyhow::anyhow!("Action Not Found!"))?;
.ok_or(ActionError::NoAction)?;
match action {
TypedAction::F32(a) => Ok(a),
_ => anyhow::bail!("wrong action type"),
_ => Err(ActionError::WrongActionType),
}
}
pub fn get_action_bool(
&self,
action_set: &'static str,
action_name: &'static str,
) -> anyhow::Result<&Action<bool>> {
) -> Result<&Action<bool>,ActionError> {
let action = self
.sets
.get(action_set)
.ok_or(anyhow::anyhow!("Action Set Not Found!"))?
.ok_or(ActionError::NoActionSet)?
.actions
.get(action_name)
.ok_or(anyhow::anyhow!("Action Not Found!"))?;
.ok_or(ActionError::NoAction)?;
match action {
TypedAction::Bool(a) => Ok(a),
_ => anyhow::bail!("wrong action type"),
_ => Err(ActionError::WrongActionType),
}
}
pub fn get_action_posef(
&self,
action_set: &'static str,
action_name: &'static str,
) -> anyhow::Result<&Action<Posef>> {
) -> Result<&Action<Posef>,ActionError> {
let action = self
.sets
.get(action_set)
.ok_or(anyhow::anyhow!("Action Set Not Found!"))?
.ok_or(ActionError::NoActionSet)?
.actions
.get(action_name)
.ok_or(anyhow::anyhow!("Action Not Found!"))?;
.ok_or(ActionError::NoAction)?;
match action {
TypedAction::PoseF(a) => Ok(a),
_ => anyhow::bail!("wrong action type"),
_ => Err(ActionError::WrongActionType),
}
}
pub fn get_action_haptic(
&self,
action_set: &'static str,
action_name: &'static str,
) -> anyhow::Result<&Action<Haptic>> {
) -> Result<&Action<Haptic>,ActionError> {
let action = self
.sets
.get(action_set)
.ok_or(anyhow::anyhow!("Action Set Not Found!"))?
.ok_or(ActionError::NoActionSet)?
.actions
.get(action_name)
.ok_or(anyhow::anyhow!("Action Not Found!"))?;
.ok_or(ActionError::NoAction)?;
match action {
TypedAction::Haptic(a) => Ok(a),
_ => anyhow::bail!("wrong action type"),
_ => Err(ActionError::WrongActionType),
}
}
}

0 comments on commit d84d02a

Please sign in to comment.