From 77f50812195d0733b0f706133ed2fe94f870e0ad Mon Sep 17 00:00:00 2001 From: Jay Christy Date: Wed, 15 May 2024 13:22:25 -0400 Subject: [PATCH] first pass at actions --- crates/bevy_openxr/examples/actions.rs | 131 ++++++++++++++++++ .../bevy_openxr/src/openxr/action_binding.rs | 1 + .../src/openxr/action_set_attaching.rs | 25 +++- 3 files changed, 154 insertions(+), 3 deletions(-) create mode 100644 crates/bevy_openxr/examples/actions.rs diff --git a/crates/bevy_openxr/examples/actions.rs b/crates/bevy_openxr/examples/actions.rs new file mode 100644 index 0000000..9ca9be2 --- /dev/null +++ b/crates/bevy_openxr/examples/actions.rs @@ -0,0 +1,131 @@ +// a simple example showing basic actions + +use std::borrow::Cow; + +use bevy::prelude::*; +use bevy_openxr::{ + action_binding::OxrSuggestActionBinding, + action_set_attaching::{AttachedActionSets, OxrAttachActionSet}, + add_xr_plugins, + resources::{OxrInstance, OxrSession}, +}; +use openxr::{ActiveActionSet, Path}; + +fn main() { + App::new() + .add_plugins(add_xr_plugins(DefaultPlugins)) + .add_plugins(bevy_xr_utils::hand_gizmos::HandGizmosPlugin) + .add_systems(Startup, setup_scene) + .add_systems(Startup, create_action) + .init_resource::() + .add_systems(Update, read_action) + .run(); +} + +/// set up a simple 3D scene +fn setup_scene( + mut commands: Commands, + mut meshes: ResMut>, + mut materials: ResMut>, +) { + // circular base + commands.spawn(PbrBundle { + mesh: meshes.add(Circle::new(4.0)), + material: materials.add(Color::WHITE), + transform: Transform::from_rotation(Quat::from_rotation_x(-std::f32::consts::FRAC_PI_2)), + ..default() + }); + // cube + commands.spawn(PbrBundle { + mesh: meshes.add(Cuboid::new(1.0, 1.0, 1.0)), + material: materials.add(Color::rgb_u8(124, 144, 255)), + transform: Transform::from_xyz(0.0, 0.5, 0.0), + ..default() + }); + // light + commands.spawn(PointLightBundle { + point_light: PointLight { + shadows_enabled: true, + ..default() + }, + transform: Transform::from_xyz(4.0, 8.0, 4.0), + ..default() + }); + commands.spawn(Camera3dBundle { + transform: Transform::from_xyz(-2.5, 4.5, 9.0).looking_at(Vec3::ZERO, Vec3::Y), + ..default() + }); +} + +#[derive(Resource, Default)] +struct TestAction { + action: Option>, +} + +fn create_action( + mut writer: EventWriter, + instance: ResMut, + mut test: ResMut, + mut set_writer: EventWriter, +) { + let name = "test"; + let pretty_name = "pretty test"; + let priority = u32::MIN; + //create action set + let set: openxr::ActionSet = instance + .create_action_set(name, pretty_name, priority) + .unwrap(); + + let action_name = "action_name"; + let localized_name = "localized_name"; + //create new action from action set + let bool_action: openxr::Action = set + .create_action::(action_name, localized_name, &[]) + .unwrap(); + + //interaction profile + let profile = Cow::from("/interaction_profiles/valve/index_controller"); + //bindings + let binding = vec![Cow::from("/user/hand/right/input/a/click")]; + let sugestion = OxrSuggestActionBinding { + action: bool_action.as_raw(), + interaction_profile: profile, + bindings: binding, + }; + + //finally send the suggestion + writer.send(sugestion); + set_writer.send(OxrAttachActionSet(set.clone())); + + test.action = Some(bool_action); +} + +fn read_action( + session: ResMut, + test: ResMut, + attached: ResMut +) { + //maybe sync before? + let why = &attached.sets.iter().map(|v| ActiveActionSet::from(v)).collect::>(); + let sync = session.sync_actions(&why[..]); + match sync { + Ok(_) =>info!("sync ok"), + Err(_) => error!("sync error"), + } + + + //now check the action? + let action = &test.action; + match action { + Some(act) => { + let thing = act.state(&session, Path::NULL); + match thing { + Ok(a) => { + info!("action state: {:?}", a); + } + Err(_) => info!("error getting state"), + } + } + None => info!("no action"), + } +} \ No newline at end of file diff --git a/crates/bevy_openxr/src/openxr/action_binding.rs b/crates/bevy_openxr/src/openxr/action_binding.rs index a5de40b..f9796c1 100644 --- a/crates/bevy_openxr/src/openxr/action_binding.rs +++ b/crates/bevy_openxr/src/openxr/action_binding.rs @@ -84,6 +84,7 @@ fn bind_actions(instance: Res, mut actions: EventReader error!("Invalid Path Suggested!"), openxr::sys::Result::ERROR_PATH_UNSUPPORTED => error!("Suggested Path Unsupported!"), + openxr::sys::Result::SUCCESS => info!("suggested binding success"), _ => {} } } diff --git a/crates/bevy_openxr/src/openxr/action_set_attaching.rs b/crates/bevy_openxr/src/openxr/action_set_attaching.rs index b788458..781c958 100644 --- a/crates/bevy_openxr/src/openxr/action_set_attaching.rs +++ b/crates/bevy_openxr/src/openxr/action_set_attaching.rs @@ -1,6 +1,7 @@ use crate::resources::OxrSession; use bevy::prelude::*; use bevy_xr::session::status_changed_to; +use openxr::ActionSet; impl Plugin for OxrActionAttachingPlugin { fn build(&self, app: &mut App) { @@ -9,15 +10,28 @@ impl Plugin for OxrActionAttachingPlugin { PostUpdate, attach_sets.run_if(status_changed_to(bevy_xr::session::XrStatus::Ready)), ); + app.init_resource::(); } } -fn attach_sets(session: Res, mut events: EventReader) { +fn attach_sets( + session: Res, + mut events: EventReader, + mut attached: ResMut, +) { let sets = events.read().map(|v| &v.0).collect::>(); - if sets.is_empty() {return;} + if sets.is_empty() { + return; + } info!("attaching {} sessions", sets.len()); match session.attach_action_sets(&sets) { - Ok(_) => {info!("attached sessions!")} + Ok(_) => { + info!("attached sessions!"); + for &set in sets.iter() { + let clone = set.clone(); + attached.sets.push(clone); + } + } Err(openxr::sys::Result::ERROR_ACTIONSETS_ALREADY_ATTACHED) => { error!("Action Sets Already attached!"); } @@ -36,3 +50,8 @@ fn attach_sets(session: Res, mut events: EventReader, +}