107 lines
2.8 KiB
Rust
107 lines
2.8 KiB
Rust
use crate::{
|
|
core::client::INTERNAL_CLIENT,
|
|
nodes::{
|
|
Node, OwnedNode,
|
|
fields::{FieldTrait, Ray},
|
|
input::{INPUT_HANDLER_REGISTRY, InputDataType, InputMethod, Pointer},
|
|
spatial::Spatial,
|
|
},
|
|
};
|
|
use color_eyre::eyre::Result;
|
|
use glam::{Mat4, vec3};
|
|
use serde::{Deserialize, Serialize};
|
|
use stardust_xr::values::Datamap;
|
|
use std::sync::Arc;
|
|
use stereokit_rust::system::Input;
|
|
|
|
#[derive(Default, Deserialize, Serialize)]
|
|
pub struct EyeDatamap {
|
|
eye: u32,
|
|
}
|
|
|
|
#[derive(Debug, Clone, Serialize)]
|
|
pub struct KeyboardEvent {
|
|
pub keyboard: String,
|
|
pub keymap: Option<String>,
|
|
pub keys_up: Option<Vec<u32>>,
|
|
pub keys_down: Option<Vec<u32>>,
|
|
}
|
|
|
|
pub struct EyePointer {
|
|
node: OwnedNode,
|
|
spatial: Arc<Spatial>,
|
|
pointer: Arc<InputMethod>,
|
|
}
|
|
impl EyePointer {
|
|
pub fn new() -> Result<Self> {
|
|
let node = Node::generate(&INTERNAL_CLIENT, false).add_to_scenegraph_owned()?;
|
|
let spatial = Spatial::add_to(&node.0, None, Mat4::IDENTITY, false);
|
|
let pointer = InputMethod::add_to(
|
|
&node.0,
|
|
InputDataType::Pointer(Pointer::default()),
|
|
Datamap::from_typed(EyeDatamap::default())?,
|
|
)
|
|
.unwrap();
|
|
|
|
Ok(EyePointer {
|
|
node,
|
|
spatial,
|
|
pointer,
|
|
})
|
|
}
|
|
pub fn update(&self) {
|
|
let ray = Input::get_eyes();
|
|
self.spatial
|
|
.set_local_transform(Mat4::from_rotation_translation(
|
|
ray.orientation.into(),
|
|
ray.position.into(),
|
|
));
|
|
{
|
|
// Set pointer input datamap
|
|
*self.pointer.datamap.lock() = Datamap::from_typed(EyeDatamap { eye: 2 }).unwrap();
|
|
}
|
|
|
|
// send input to all the input handlers that are the closest to the ray as possible
|
|
let rx = INPUT_HANDLER_REGISTRY
|
|
.get_valid_contents()
|
|
.into_iter()
|
|
// filter out all the disabled handlers
|
|
.filter(|handler| {
|
|
let Some(node) = handler.spatial.node() else {
|
|
return false;
|
|
};
|
|
node.enabled()
|
|
})
|
|
// ray march to all the enabled handlers' fields
|
|
.map(|handler| {
|
|
let result = handler.field.ray_march(Ray {
|
|
origin: vec3(0.0, 0.0, 0.0),
|
|
direction: vec3(0.0, 0.0, -1.0),
|
|
space: self.spatial.clone(),
|
|
});
|
|
(vec![handler], result)
|
|
})
|
|
// make sure the field isn't at the pointer origin and that it's being hit
|
|
.filter(|(_, result)| result.deepest_point_distance > 0.01 && result.min_distance < 0.0)
|
|
// .inspect(|(_, result)| {
|
|
// dbg!(result);
|
|
// })
|
|
// now collect all handlers that are same distance if they're the closest
|
|
.reduce(|(mut handlers_a, result_a), (handlers_b, result_b)| {
|
|
if (result_a.deepest_point_distance - result_b.deepest_point_distance).abs() < 0.001
|
|
{
|
|
// distance is basically the same
|
|
handlers_a.extend(handlers_b);
|
|
(handlers_a, result_a)
|
|
} else if result_a.deepest_point_distance < result_b.deepest_point_distance {
|
|
(handlers_a, result_a)
|
|
} else {
|
|
(handlers_b, result_b)
|
|
}
|
|
})
|
|
.map(|(rx, _)| rx)
|
|
.unwrap_or_default();
|
|
self.pointer.set_handler_order(rx.iter());
|
|
}
|
|
}
|