added initial interactions
This commit is contained in:
@@ -12,7 +12,7 @@ anyhow = "1.0.75"
|
|||||||
ash = "0.37.3"
|
ash = "0.37.3"
|
||||||
bevy = { git = "https://github.com/awtterpip/bevy", default-features = false, features = [
|
bevy = { git = "https://github.com/awtterpip/bevy", default-features = false, features = [
|
||||||
"bevy_render",
|
"bevy_render",
|
||||||
], rev = "ac28b11797c0a85b431ee4940c6afa434f712f7a" }
|
] }
|
||||||
openxr = { version = "0.17.1", features = ["mint"] }
|
openxr = { version = "0.17.1", features = ["mint"] }
|
||||||
mint = "0.5.9"
|
mint = "0.5.9"
|
||||||
wgpu = "0.16.0"
|
wgpu = "0.16.0"
|
||||||
@@ -20,7 +20,7 @@ wgpu-core = { version = "0.16.0", features = ["vulkan"] }
|
|||||||
wgpu-hal = "0.16.0"
|
wgpu-hal = "0.16.0"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
bevy = { git = "https://github.com/awtterpip/bevy", rev = "ac28b11797c0a85b431ee4940c6afa434f712f7a" }
|
bevy = { git = "https://github.com/awtterpip/bevy" }
|
||||||
color-eyre = "0.6.2"
|
color-eyre = "0.6.2"
|
||||||
|
|
||||||
[[example]]
|
[[example]]
|
||||||
|
|||||||
@@ -1,11 +1,19 @@
|
|||||||
use bevy::diagnostic::{FrameTimeDiagnosticsPlugin, LogDiagnosticsPlugin};
|
use bevy::diagnostic::{FrameTimeDiagnosticsPlugin, LogDiagnosticsPlugin};
|
||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
use bevy::transform::components::Transform;
|
use bevy::transform::components::Transform;
|
||||||
|
use bevy_openxr::input::XrInput;
|
||||||
|
use bevy_openxr::resources::{XrFrameState, XrInstance, XrSession};
|
||||||
use bevy_openxr::xr_input::debug_gizmos::OpenXrDebugRenderer;
|
use bevy_openxr::xr_input::debug_gizmos::OpenXrDebugRenderer;
|
||||||
|
use bevy_openxr::xr_input::interactions::{
|
||||||
|
draw_interaction_gizmos, hover_interaction, XRDirectInteractor, XRInteractable,
|
||||||
|
XRInteractableState, XRInteractorState,
|
||||||
|
};
|
||||||
|
use bevy_openxr::xr_input::oculus_touch::OculusController;
|
||||||
use bevy_openxr::xr_input::prototype_locomotion::{proto_locomotion, PrototypeLocomotionConfig};
|
use bevy_openxr::xr_input::prototype_locomotion::{proto_locomotion, PrototypeLocomotionConfig};
|
||||||
use bevy_openxr::xr_input::trackers::{
|
use bevy_openxr::xr_input::trackers::{
|
||||||
OpenXRController, OpenXRLeftController, OpenXRRightController, OpenXRTracker,
|
OpenXRController, OpenXRLeftController, OpenXRRightController, OpenXRTracker,
|
||||||
};
|
};
|
||||||
|
use bevy_openxr::xr_input::Hand;
|
||||||
use bevy_openxr::DefaultXrPlugins;
|
use bevy_openxr::DefaultXrPlugins;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
@@ -21,6 +29,9 @@ fn main() {
|
|||||||
.add_systems(Update, proto_locomotion)
|
.add_systems(Update, proto_locomotion)
|
||||||
.add_systems(Startup, spawn_controllers_example)
|
.add_systems(Startup, spawn_controllers_example)
|
||||||
.insert_resource(PrototypeLocomotionConfig::default())
|
.insert_resource(PrototypeLocomotionConfig::default())
|
||||||
|
.add_systems(Update, draw_interaction_gizmos)
|
||||||
|
.add_systems(Update, hover_interaction)
|
||||||
|
.add_systems(Update, prototype_interaction_input)
|
||||||
.run();
|
.run();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,6 +76,15 @@ fn setup(
|
|||||||
transform: Transform::from_xyz(-2.0, 2.5, 5.0).looking_at(Vec3::ZERO, Vec3::Y),
|
transform: Transform::from_xyz(-2.0, 2.5, 5.0).looking_at(Vec3::ZERO, Vec3::Y),
|
||||||
..default()
|
..default()
|
||||||
},));
|
},));
|
||||||
|
//simple interactable
|
||||||
|
commands.spawn((
|
||||||
|
SpatialBundle {
|
||||||
|
transform: Transform::from_xyz(0.0, 1.0, 0.0),
|
||||||
|
..default()
|
||||||
|
},
|
||||||
|
XRInteractable,
|
||||||
|
XRInteractableState::default(),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn spawn_controllers_example(mut commands: Commands) {
|
fn spawn_controllers_example(mut commands: Commands) {
|
||||||
@@ -74,6 +94,8 @@ fn spawn_controllers_example(mut commands: Commands) {
|
|||||||
OpenXRController,
|
OpenXRController,
|
||||||
OpenXRTracker,
|
OpenXRTracker,
|
||||||
SpatialBundle::default(),
|
SpatialBundle::default(),
|
||||||
|
XRDirectInteractor,
|
||||||
|
XRInteractorState::default(),
|
||||||
));
|
));
|
||||||
//right hand
|
//right hand
|
||||||
commands.spawn((
|
commands.spawn((
|
||||||
@@ -81,5 +103,52 @@ fn spawn_controllers_example(mut commands: Commands) {
|
|||||||
OpenXRController,
|
OpenXRController,
|
||||||
OpenXRTracker,
|
OpenXRTracker,
|
||||||
SpatialBundle::default(),
|
SpatialBundle::default(),
|
||||||
|
XRDirectInteractor,
|
||||||
|
XRInteractorState::default(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn prototype_interaction_input(
|
||||||
|
oculus_controller: Res<OculusController>,
|
||||||
|
frame_state: Res<XrFrameState>,
|
||||||
|
xr_input: Res<XrInput>,
|
||||||
|
instance: Res<XrInstance>,
|
||||||
|
session: Res<XrSession>,
|
||||||
|
mut right_interactor_query: Query<
|
||||||
|
(&mut XRInteractorState),
|
||||||
|
(
|
||||||
|
With<XRDirectInteractor>,
|
||||||
|
With<OpenXRRightController>,
|
||||||
|
Without<OpenXRLeftController>,
|
||||||
|
),
|
||||||
|
>,
|
||||||
|
mut left_interactor_query: Query<
|
||||||
|
(&mut XRInteractorState),
|
||||||
|
(
|
||||||
|
With<XRDirectInteractor>,
|
||||||
|
With<OpenXRLeftController>,
|
||||||
|
Without<OpenXRRightController>,
|
||||||
|
),
|
||||||
|
>,
|
||||||
|
) {
|
||||||
|
//lock frame
|
||||||
|
let frame_state = *frame_state.lock().unwrap();
|
||||||
|
//get controller
|
||||||
|
let controller = oculus_controller.get_ref(&instance, &session, &frame_state, &xr_input);
|
||||||
|
//get controller triggers
|
||||||
|
let left_trigger = controller.trigger(Hand::Left);
|
||||||
|
let right_trigger = controller.trigger(Hand::Right);
|
||||||
|
//get the interactors and do state stuff
|
||||||
|
let mut left_state = left_interactor_query.single_mut();
|
||||||
|
if left_trigger > 0.8 {
|
||||||
|
*left_state = XRInteractorState::Selecting;
|
||||||
|
} else {
|
||||||
|
*left_state = XRInteractorState::Idle;
|
||||||
|
}
|
||||||
|
let mut right_state = right_interactor_query.single_mut();
|
||||||
|
if right_trigger > 0.8 {
|
||||||
|
*right_state = XRInteractorState::Selecting;
|
||||||
|
} else {
|
||||||
|
*right_state = XRInteractorState::Idle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
123
src/xr_input/interactions.rs
Normal file
123
src/xr_input/interactions.rs
Normal file
@@ -0,0 +1,123 @@
|
|||||||
|
use std::f32::consts::PI;
|
||||||
|
|
||||||
|
use bevy::prelude::{
|
||||||
|
info, Color, Component, Gizmos, GlobalTransform, Quat, Query, Vec3, With, Without,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Component)]
|
||||||
|
pub struct XRDirectInteractor;
|
||||||
|
#[derive(Component)]
|
||||||
|
pub enum XRInteractableState {
|
||||||
|
Idle,
|
||||||
|
Hover,
|
||||||
|
Select,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for XRInteractableState {
|
||||||
|
fn default() -> Self {
|
||||||
|
XRInteractableState::Idle
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Component)]
|
||||||
|
pub enum XRInteractorState {
|
||||||
|
Idle,
|
||||||
|
Selecting,
|
||||||
|
}
|
||||||
|
impl Default for XRInteractorState {
|
||||||
|
fn default() -> Self {
|
||||||
|
XRInteractorState::Idle
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Component)]
|
||||||
|
pub struct XRInteractable;
|
||||||
|
|
||||||
|
pub fn draw_interaction_gizmos(
|
||||||
|
mut gizmos: Gizmos,
|
||||||
|
interactable_query: Query<
|
||||||
|
(&GlobalTransform, &XRInteractableState),
|
||||||
|
(With<XRInteractable>, Without<XRDirectInteractor>),
|
||||||
|
>,
|
||||||
|
interactor_query: Query<
|
||||||
|
(&GlobalTransform, &XRInteractorState),
|
||||||
|
(With<XRDirectInteractor>, Without<XRInteractable>),
|
||||||
|
>,
|
||||||
|
) {
|
||||||
|
for (global_transform, interactable_state) in interactable_query.iter() {
|
||||||
|
let transform = global_transform.compute_transform();
|
||||||
|
let color = match interactable_state {
|
||||||
|
XRInteractableState::Idle => Color::RED,
|
||||||
|
XRInteractableState::Hover => Color::YELLOW,
|
||||||
|
XRInteractableState::Select => Color::GREEN,
|
||||||
|
};
|
||||||
|
gizmos.sphere(transform.translation, transform.rotation, 0.1, color);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (interactor_global_transform, interactor_state) in interactor_query.iter() {
|
||||||
|
let mut transform = interactor_global_transform.compute_transform();
|
||||||
|
transform.scale = Vec3::splat(0.1);
|
||||||
|
let quat = Quat::from_euler(
|
||||||
|
bevy::prelude::EulerRot::XYZ,
|
||||||
|
45.0 * (PI / 180.0),
|
||||||
|
0.0,
|
||||||
|
45.0 * (PI / 180.0),
|
||||||
|
);
|
||||||
|
transform.rotation = quat;
|
||||||
|
let color = match interactor_state {
|
||||||
|
XRInteractorState::Idle => Color::BLUE,
|
||||||
|
XRInteractorState::Selecting => Color::PURPLE,
|
||||||
|
};
|
||||||
|
gizmos.cuboid(transform, color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn hover_interaction(
|
||||||
|
mut interactable_query: Query<
|
||||||
|
(&GlobalTransform, &mut XRInteractableState),
|
||||||
|
(With<XRInteractable>, Without<XRDirectInteractor>),
|
||||||
|
>,
|
||||||
|
interactor_query: Query<
|
||||||
|
(&GlobalTransform, &XRInteractorState),
|
||||||
|
(With<XRDirectInteractor>, Without<XRInteractable>),
|
||||||
|
>,
|
||||||
|
) {
|
||||||
|
'interactable: for (xr_interactable_global_transform, mut state) in
|
||||||
|
interactable_query.iter_mut()
|
||||||
|
{
|
||||||
|
let mut hovered = false;
|
||||||
|
let mut selected = false;
|
||||||
|
for (interactor_global_transform, interactor_state) in interactor_query.iter() {
|
||||||
|
//check for sphere overlaps
|
||||||
|
let size = 0.1;
|
||||||
|
if interactor_global_transform
|
||||||
|
.compute_transform()
|
||||||
|
.translation
|
||||||
|
.distance_squared(
|
||||||
|
xr_interactable_global_transform
|
||||||
|
.compute_transform()
|
||||||
|
.translation,
|
||||||
|
)
|
||||||
|
< (size * size) * 2.0
|
||||||
|
{
|
||||||
|
info!("we overlapping");
|
||||||
|
//check for selections first
|
||||||
|
match interactor_state {
|
||||||
|
XRInteractorState::Idle => hovered = true,
|
||||||
|
XRInteractorState::Selecting => {
|
||||||
|
selected = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//check what we found
|
||||||
|
//also i dont like this
|
||||||
|
if selected {
|
||||||
|
*state = XRInteractableState::Select;
|
||||||
|
} else if hovered {
|
||||||
|
*state = XRInteractableState::Hover;
|
||||||
|
} else {
|
||||||
|
*state = XRInteractableState::Idle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
pub mod controllers;
|
pub mod controllers;
|
||||||
pub mod debug_gizmos;
|
pub mod debug_gizmos;
|
||||||
|
pub mod interactions;
|
||||||
pub mod oculus_touch;
|
pub mod oculus_touch;
|
||||||
pub mod prototype_locomotion;
|
pub mod prototype_locomotion;
|
||||||
pub mod trackers;
|
pub mod trackers;
|
||||||
|
|||||||
Reference in New Issue
Block a user