diff --git a/crates/bevy_openxr/examples/common_entities.rs b/crates/bevy_openxr/examples/common_entities.rs new file mode 100644 index 0000000..20c3da1 --- /dev/null +++ b/crates/bevy_openxr/examples/common_entities.rs @@ -0,0 +1,168 @@ +//! A simple 3D scene with light shining over a cube sitting on a plane. + +use std::ops::Deref; + +use bevy::prelude::*; +use bevy_mod_openxr::{ + action_binding::{OxrSendActionBindings, OxrSuggestActionBinding}, + action_set_attaching::OxrAttachActionSet, + action_set_syncing::{OxrActionSetSyncSet, OxrSyncActionSet}, + add_xr_plugins, + resources::OxrInstance, + session::OxrSession, + spaces::OxrSpaceExt, +}; +use bevy_mod_xr::{ + session::{session_available, session_running, XrSessionCreated, XrTrackingRoot}, + spaces::XrSpace, + types::XrPose, +}; +use openxr::Posef; + +fn main() { + let mut app = App::new(); + app.add_plugins(add_xr_plugins(DefaultPlugins)); + app.add_systems(Startup, setup); + //create bindings + app.add_systems(OxrSendActionBindings, suggest_action_bindings); + //sync actions + app.add_systems( + PreUpdate, + sync_actions + .before(OxrActionSetSyncSet) + .run_if(session_running), + ); + //things? + app.add_systems(XrSessionCreated, spawn_hands); + app.add_systems(XrSessionCreated, attach_set); + app.add_systems(Startup, create_actions.run_if(session_available)); + + app.run(); +} + +/// set up a simple 3D scene +fn setup( + 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::srgb_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)] +struct ControllerActions { + set: openxr::ActionSet, + left: openxr::Action, + right: openxr::Action, +} + +fn suggest_action_bindings( + actions: Res, + mut bindings: EventWriter, +) { + bindings.send(OxrSuggestActionBinding { + action: actions.left.as_raw(), + interaction_profile: "/interaction_profiles/oculus/touch_controller".into(), + bindings: vec!["/user/hand/left/input/grip/pose".into()], + }); + bindings.send(OxrSuggestActionBinding { + action: actions.right.as_raw(), + interaction_profile: "/interaction_profiles/oculus/touch_controller".into(), + bindings: vec!["/user/hand/right/input/grip/pose".into()], + }); +} + +fn sync_actions(actions: Res, mut sync: EventWriter) { + sync.send(OxrSyncActionSet(actions.set.clone())); +} + +fn attach_set(actions: Res, mut attach: EventWriter) { + attach.send(OxrAttachActionSet(actions.set.clone())); +} + +fn create_actions(instance: Res, mut cmds: Commands) { + let set = instance.create_action_set("hands", "Hands", 0).unwrap(); + let left = set + .create_action("left_pose", "Left Hand Grip Pose", &[]) + .unwrap(); + let right = set + .create_action("right_pose", "Right Hand Grip Pose", &[]) + .unwrap(); + + cmds.insert_resource(ControllerActions { set, left, right }) +} + +fn spawn_hands( + actions: Res, + mut cmds: Commands, + root: Query>, + session: Res, + mut meshes: ResMut>, + mut materials: ResMut>, +) { + // This is a demonstation of how to integrate with the openxr crate, the right space is the + // recommended way + let left_space = XrSpace::from_openxr_space( + actions + .left + .create_space( + session.deref().deref().clone(), + openxr::Path::NULL, + Posef::IDENTITY, + ) + .unwrap(), + ); + let right_space = session + .create_action_space(&actions.right, openxr::Path::NULL, XrPose::IDENTITY) + .unwrap(); + let left = cmds + .spawn(( + PbrBundle { + mesh: meshes.add(Cuboid::new(0.1, 0.1, 0.05)), + material: materials.add(Color::srgb_u8(124, 144, 255)), + transform: Transform::from_xyz(0.0, 0.5, 0.0), + ..default() + }, + left_space, + )) + .id(); + let right = cmds + .spawn(( + PbrBundle { + mesh: meshes.add(Cuboid::new(0.1, 0.1, 0.05)), + material: materials.add(Color::srgb_u8(124, 144, 255)), + transform: Transform::from_xyz(0.0, 0.5, 0.0), + ..default() + }, + right_space, + )) + .id(); + + cmds.entity(root.single()).push_children(&[left, right]); +}