add support for Vec2 Actions, slightly changed the way actions are created but no functionality change and changed the get_action_* return result to a custom error (#57)

This commit is contained in:
Schmarni
2023-12-12 01:26:55 +01:00
committed by GitHub
parent 2e492e120c
commit 248d160ae5

View File

@@ -1,8 +1,13 @@
use std::error::Error;
use bevy::{prelude::*, utils::HashMap}; use bevy::{prelude::*, utils::HashMap};
use openxr as xr; 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; use super::oculus_touch::ActionSets;
@@ -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) { pub fn setup_oxr_actions(world: &mut World) {
let actions = world.remove_resource::<SetupActionSets>().unwrap(); let actions = world.remove_resource::<SetupActionSets>().unwrap();
let instance = world.get_resource::<XrInstance>().unwrap(); let instance = world.get_resource::<XrInstance>().unwrap();
@@ -27,50 +48,33 @@ pub fn setup_oxr_actions(world: &mut World) {
let mut oxr_action_sets = Vec::new(); let mut oxr_action_sets = Vec::new();
let mut action_sets = XrActionSets { sets: default() }; let mut action_sets = XrActionSets { sets: default() };
// let mut action_bindings: HashMap<&'static str, Vec<xr::Path>> = HashMap::new(); // 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< let mut action_bindings: HashMap<
(&'static str, &'static str), (&'static str, &'static str),
HashMap<&'static str, Vec<xr::Path>>, HashMap<&'static str, Vec<xr::Path>>,
> = HashMap::new(); > = 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 mut actions: HashMap<&'static str, TypedAction> = default();
let oxr_action_set = instance let oxr_action_set = instance
.create_action_set(set_name, &set.pretty_name, set.priority) .create_action_set(set_name, &set.pretty_name, set.priority)
.expect("Unable to create action set"); .expect("Unable to create action set");
for (action_name, action) in set.actions.into_iter() { for (action_name, action) in set.actions.into_iter() {
use self::create_action as ca;
let typed_action = match action.action_type { let typed_action = match action.action_type {
ActionType::F32 => TypedAction::F32(match action.handednes { ActionType::Vec2 => {
ActionHandednes::Single => oxr_action_set TypedAction::Vec2(ca(&action, action_name, &oxr_action_set, &hands))
.create_action(action_name, &action.pretty_name, &[]) }
.expect(&format!("Unable to create action: {}", action_name)), ActionType::F32 => {
ActionHandednes::Double => oxr_action_set TypedAction::F32(ca(&action, action_name, &oxr_action_set, &hands))
.create_action(action_name, &action.pretty_name, &hands) }
.expect(&format!("Unable to create action: {}", action_name)), ActionType::Bool => {
}), TypedAction::Bool(ca(&action, action_name, &oxr_action_set, &hands))
ActionType::Bool => TypedAction::Bool(match action.handednes { }
ActionHandednes::Single => oxr_action_set ActionType::PoseF => {
.create_action(action_name, &action.pretty_name, &[]) TypedAction::PoseF(ca(&action, action_name, &oxr_action_set, &hands))
.expect(&format!("Unable to create action: {}", action_name)), }
ActionHandednes::Double => oxr_action_set ActionType::Haptic => {
.create_action(action_name, &action.pretty_name, &hands) TypedAction::Haptic(ca(&action, action_name, &oxr_action_set, &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)),
}),
}; };
actions.insert(action_name, typed_action); actions.insert(action_name, typed_action);
for (device_path, bindings) in action.bindings.into_iter() { for (device_path, bindings) in action.bindings.into_iter() {
@@ -107,18 +111,19 @@ pub fn setup_oxr_actions(world: &mut World) {
.zip([&action_bindings].into_iter().cycle()) .zip([&action_bindings].into_iter().cycle())
.flat_map(move |((set_name, action_name, action), bindings)| { .flat_map(move |((set_name, action_name, action), bindings)| {
bindings bindings
.get(&(set_name.clone(), action_name.clone())) .get(&(set_name as &'static str, action_name as &'static str))
.unwrap() .unwrap()
.iter() .iter()
.map(move |(dev, bindings)| (action.clone(), dev.clone(), bindings)) .map(move |(dev, bindings)| (action, dev, bindings))
}) })
.map(|(action, dev, bindings)| { .map(|(action, dev, bindings)| {
info!("Hi"); info!("Hi");
( (
dev, dev,
bindings bindings
.into_iter() .iter()
.map(move |binding| match &action { .map(move |binding| match &action {
TypedAction::Vec2(a) => Binding::new(a, *binding),
TypedAction::F32(a) => Binding::new(a, *binding), TypedAction::F32(a) => Binding::new(a, *binding),
TypedAction::Bool(a) => Binding::new(a, *binding), TypedAction::Bool(a) => Binding::new(a, *binding),
TypedAction::PoseF(a) => Binding::new(a, *binding), TypedAction::PoseF(a) => Binding::new(a, *binding),
@@ -155,6 +160,7 @@ pub enum ActionType {
Bool, Bool,
PoseF, PoseF,
Haptic, Haptic,
Vec2,
} }
pub enum TypedAction { pub enum TypedAction {
@@ -162,6 +168,7 @@ pub enum TypedAction {
Bool(Action<bool>), Bool(Action<bool>),
PoseF(Action<Posef>), PoseF(Action<Posef>),
Haptic(Action<Haptic>), Haptic(Action<Haptic>),
Vec2(Action<Vector2f>),
} }
pub struct SetupAction { pub struct SetupAction {
@@ -247,7 +254,7 @@ impl SetupActionSets {
} }
pub struct ActionSet { pub struct ActionSet {
// oxr_action_set: xr::ActionSet, // add functionality to enable/disable action sets
enabled: bool, enabled: bool,
actions: HashMap<&'static str, TypedAction>, actions: HashMap<&'static str, TypedAction>,
} }
@@ -257,73 +264,109 @@ pub struct XrActionSets {
sets: HashMap<&'static str, ActionSet>, 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 { 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( pub fn get_action_f32(
&self, &self,
action_set: &'static str, action_set: &'static str,
action_name: &'static str, action_name: &'static str,
) -> anyhow::Result<&Action<f32>> { ) -> Result<&Action<f32>,ActionError> {
let action = self let action = self
.sets .sets
.get(action_set) .get(action_set)
.ok_or(anyhow::anyhow!("Action Set Not Found!"))? .ok_or(ActionError::NoActionSet)?
.actions .actions
.get(action_name) .get(action_name)
.ok_or(anyhow::anyhow!("Action Not Found!"))?; .ok_or(ActionError::NoAction)?;
match action { match action {
TypedAction::F32(a) => Ok(a), TypedAction::F32(a) => Ok(a),
_ => anyhow::bail!("wrong action type"), _ => Err(ActionError::WrongActionType),
} }
} }
pub fn get_action_bool( pub fn get_action_bool(
&self, &self,
action_set: &'static str, action_set: &'static str,
action_name: &'static str, action_name: &'static str,
) -> anyhow::Result<&Action<bool>> { ) -> Result<&Action<bool>,ActionError> {
let action = self let action = self
.sets .sets
.get(action_set) .get(action_set)
.ok_or(anyhow::anyhow!("Action Set Not Found!"))? .ok_or(ActionError::NoActionSet)?
.actions .actions
.get(action_name) .get(action_name)
.ok_or(anyhow::anyhow!("Action Not Found!"))?; .ok_or(ActionError::NoAction)?;
match action { match action {
TypedAction::Bool(a) => Ok(a), TypedAction::Bool(a) => Ok(a),
_ => anyhow::bail!("wrong action type"), _ => Err(ActionError::WrongActionType),
} }
} }
pub fn get_action_posef( pub fn get_action_posef(
&self, &self,
action_set: &'static str, action_set: &'static str,
action_name: &'static str, action_name: &'static str,
) -> anyhow::Result<&Action<Posef>> { ) -> Result<&Action<Posef>,ActionError> {
let action = self let action = self
.sets .sets
.get(action_set) .get(action_set)
.ok_or(anyhow::anyhow!("Action Set Not Found!"))? .ok_or(ActionError::NoActionSet)?
.actions .actions
.get(action_name) .get(action_name)
.ok_or(anyhow::anyhow!("Action Not Found!"))?; .ok_or(ActionError::NoAction)?;
match action { match action {
TypedAction::PoseF(a) => Ok(a), TypedAction::PoseF(a) => Ok(a),
_ => anyhow::bail!("wrong action type"), _ => Err(ActionError::WrongActionType),
} }
} }
pub fn get_action_haptic( pub fn get_action_haptic(
&self, &self,
action_set: &'static str, action_set: &'static str,
action_name: &'static str, action_name: &'static str,
) -> anyhow::Result<&Action<Haptic>> { ) -> Result<&Action<Haptic>,ActionError> {
let action = self let action = self
.sets .sets
.get(action_set) .get(action_set)
.ok_or(anyhow::anyhow!("Action Set Not Found!"))? .ok_or(ActionError::NoActionSet)?
.actions .actions
.get(action_name) .get(action_name)
.ok_or(anyhow::anyhow!("Action Not Found!"))?; .ok_or(ActionError::NoAction)?;
match action { match action {
TypedAction::Haptic(a) => Ok(a), TypedAction::Haptic(a) => Ok(a),
_ => anyhow::bail!("wrong action type"), _ => Err(ActionError::WrongActionType),
} }
} }
} }