diff --git a/crates/bevy_openxr/examples/actions.rs b/crates/bevy_openxr/examples/actions.rs index 9ca9be2..16b0d9b 100644 --- a/crates/bevy_openxr/examples/actions.rs +++ b/crates/bevy_openxr/examples/actions.rs @@ -2,23 +2,25 @@ use std::borrow::Cow; -use bevy::prelude::*; +use bevy::{prelude::*, utils::hashbrown::HashMap}; use bevy_openxr::{ action_binding::OxrSuggestActionBinding, action_set_attaching::{AttachedActionSets, OxrAttachActionSet}, add_xr_plugins, resources::{OxrInstance, OxrSession}, }; -use openxr::{ActiveActionSet, Path}; +use openxr::{ActionType, 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) + // .add_systems(Startup, create_action) + .add_systems(Startup, create_action_entities) + .add_systems(Startup, create_openxr_events.after(create_action_entities)) .run(); } @@ -103,17 +105,20 @@ fn create_action( fn read_action( session: ResMut, test: ResMut, - attached: ResMut + attached: ResMut, ) { //maybe sync before? - let why = &attached.sets.iter().map(|v| ActiveActionSet::from(v)).collect::>(); + let why = &attached + .sets + .iter() + .map(|v| ActiveActionSet::from(v)) + .collect::>(); let sync = session.sync_actions(&why[..]); match sync { - Ok(_) =>info!("sync ok"), + Ok(_) => info!("sync ok"), Err(_) => error!("sync error"), } - //now check the action? let action = &test.action; match action { @@ -128,4 +133,112 @@ fn read_action( } None => info!("no action"), } -} \ No newline at end of file +} + +#[derive(Component)] +struct CreateActionSet { + name: Cow<'static, str>, + pretty_name: Cow<'static, str>, + priority: u32, +} + +#[derive(Component)] +struct CreateAction { + action_name: Cow<'static, str>, + localized_name: Cow<'static, str>, + action_type: ActionType, +} + +#[derive(Component)] +struct CreateBinding { + profile: Cow<'static, str>, + binding: Cow<'static, str>, +} + +fn create_action_entities(mut commands: Commands) { + //create a set + let set = commands + .spawn(CreateActionSet { + name: "test".into(), + pretty_name: "pretty test".into(), + priority: u32::MIN, + }) + .id(); + //create an action + let action = commands + .spawn(CreateAction { + action_name: "action_name".into(), + localized_name: "localized_name".into(), + action_type: ActionType::BOOLEAN_INPUT, + }) + .id(); + + //create a binding + let binding = commands + .spawn(CreateBinding { + profile: "/interaction_profiles/valve/index_controller".into(), + binding: "/user/hand/right/input/a/click".into(), + }) + .id(); + + //add action to set, this isnt the best + //TODO look into a better system + commands.entity(action).add_child(binding); + commands.entity(set).add_child(action); +} + +fn create_openxr_events( + ActionSetsQuery: Query<(&CreateActionSet, &Children)>, + ActionsQuery: Query<(&CreateAction, &Children)>, + BindingsQuery: Query<&CreateBinding>, + instance: ResMut, + mut binding_writer: EventWriter, + mut attach_writer: EventWriter, + //please remove this + mut test: ResMut, +) { + //lets create some sets! + //we gonna need a collection of these sets for later + // let mut ActionSets = HashMap::new(); + for (set, children) in ActionSetsQuery.iter() { + //create action set + let action_set: openxr::ActionSet = instance + .create_action_set(&set.name, &set.pretty_name, set.priority) + .unwrap(); + + // ActionSets.insert(set.name.clone(), action_set); + //since the actions are made from the sets lets go + for &child in children.iter() { + //first get the action entity and stuff + let (create_action, bindings) = ActionsQuery.get(child).unwrap(); + //lets create dat actions + let bool_action: openxr::Action = action_set + .create_action::( + &create_action.action_name, + &create_action.localized_name, + &[], + ) + .unwrap(); + //TODO remove this crap + test.action = Some(bool_action.clone()); + //since we need actions for bindings lets go!! + for &bind in bindings.iter() { + //interaction profile + //get the binding entity and stuff + let create_binding = BindingsQuery.get(bind).unwrap(); + let profile = Cow::from(create_binding.profile.clone()); + //bindings + let binding = vec![Cow::from(create_binding.binding.clone())]; + let sugestion = OxrSuggestActionBinding { + action: bool_action.as_raw(), + interaction_profile: profile, + bindings: binding, + }; + //finally send the suggestion + binding_writer.send(sugestion); + } + } + + attach_writer.send(OxrAttachActionSet(action_set)); + } +}