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:
@@ -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),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user