diff --git a/src/objects/input/mouse_pointer.rs b/src/objects/input/mouse_pointer.rs index ba8987c..629260d 100644 --- a/src/objects/input/mouse_pointer.rs +++ b/src/objects/input/mouse_pointer.rs @@ -1,30 +1,58 @@ -use crate::nodes::{ - input::{pointer::Pointer, InputMethod, InputType}, - spatial::Spatial, +use crate::{ + core::client::INTERNAL_CLIENT, + nodes::{ + data::{mask_matches, Mask, PulseSender, PULSE_RECEIVER_REGISTRY}, + fields::Ray, + input::{pointer::Pointer, InputMethod, InputType}, + spatial::Spatial, + Node, + }, }; use glam::{vec3, Mat4}; +use nanoid::nanoid; use stardust_xr::{schemas::flat::Datamap, values::Transform}; -use std::sync::{Arc, Weak}; +use std::{convert::TryFrom, sync::Arc}; use stereokit::{ - input::{ButtonState, Key, Ray}, + input::{ButtonState, Key, Ray as SkRay}, StereoKit, }; +const SK_KEYMAP: &'static str = include_str!("sk.kmp"); + pub struct MousePointer { + node: Arc, + spatial: Arc, pointer: Arc, + keyboard_sender: Arc, } impl MousePointer { pub fn new() -> Self { + let node = Node::create(&INTERNAL_CLIENT, "", &nanoid!(), false).add_to_scenegraph(); + let spatial = Spatial::add_to(&node, None, Mat4::IDENTITY, false).unwrap(); + let pointer = + InputMethod::add_to(&node, InputType::Pointer(Pointer::default()), None).unwrap(); + + let keyboard_mask = { + let mut fbb = flexbuffers::Builder::default(); + let mut map = fbb.start_map(); + map.push("keyboard", "xkbv1"); + map.end_map(); + Mask(fbb.take_buffer()) + }; + let keyboard_sender = PulseSender::add_to(&node, keyboard_mask).unwrap(); + MousePointer { - pointer: InputMethod::new( - Spatial::new(Weak::new(), None, Mat4::IDENTITY), - InputType::Pointer(Pointer::default()), - ), + node, + spatial, + pointer, + keyboard_sender, } } pub fn update(&self, sk: &StereoKit) { - if let Some(ray) = Ray::from_mouse(sk.input_mouse()) { - self.pointer.spatial.set_local_transform_components( + let mouse = sk.input_mouse(); + + if let Some(ray) = SkRay::from_mouse(mouse) { + self.spatial.set_local_transform_components( None, Transform { position: Some(ray.pos), @@ -35,25 +63,95 @@ impl MousePointer { }, ); } - let mut fbb = flexbuffers::Builder::default(); - let mut map = fbb.start_map(); - map.push( - "select", - if sk.input_key(Key::MouseLeft).contains(ButtonState::Active) { - 1.0f32 - } else { - 0.0f32 - }, - ); - map.push( - "grab", - if sk.input_key(Key::MouseRight).contains(ButtonState::Active) { - 1.0f32 - } else { - 0.0f32 - }, - ); - map.end_map(); - *self.pointer.datamap.lock() = Datamap::new(fbb.take_buffer()).ok(); + { + // Set pointer input datamap + let mut fbb = flexbuffers::Builder::default(); + let mut map = fbb.start_map(); + map.push( + "select", + if sk.input_key(Key::MouseLeft).contains(ButtonState::Active) { + 1.0f32 + } else { + 0.0f32 + }, + ); + map.push( + "grab", + if sk.input_key(Key::MouseRight).contains(ButtonState::Active) { + 1.0f32 + } else { + 0.0f32 + }, + ); + let mut scroll_vec = map.start_vector("scroll"); + scroll_vec.push(0_f32); + scroll_vec.push(mouse.scroll_change / 120.0); + scroll_vec.end_vector(); + map.end_map(); + *self.pointer.datamap.lock() = Datamap::new(fbb.take_buffer()).ok(); + } + self.send_keyboard_input(sk); + } + + fn send_keyboard_input(&self, sk: &StereoKit) { + let rx = PULSE_RECEIVER_REGISTRY + .get_valid_contents() + .into_iter() + .filter(|rx| mask_matches(&rx.mask, &self.keyboard_sender.mask)) + .map(|rx| { + let result = rx.field.ray_march(Ray { + origin: vec3(0.0, 0.0, 0.0), + direction: vec3(0.0, 0.0, 1.0), + space: self.spatial.clone(), + }); + (rx, result) + }) + .filter(|(_rx, result)| { + result.deepest_point_distance > 0.0 && result.min_distance < 0.05 + }) + .reduce(|(rx_a, result_a), (rx_b, result_b)| { + if result_a.deepest_point_distance < result_b.deepest_point_distance { + (rx_a, result_a) + } else { + (rx_b, result_b) + } + }) + .map(|(rx, _)| rx); + + if let Some(rx) = rx { + let mut keys_up = vec![]; + let mut keys_down = vec![]; + for (key, state) in (1_u32..254) + .filter_map(|i| Some((i, Key::try_from(i).ok()?))) + .map(|(i, k)| (i, sk.input_key(k))) + .filter(|(_, k)| k.contains(ButtonState::Changed)) + { + if state.contains(ButtonState::Active) { + keys_down.push(key); + } else { + keys_up.push(key); + } + } + + let mut fbb = flexbuffers::Builder::default(); + { + let mut map = fbb.start_map(); + map.push("keyboard", "xkbv1"); + map.push("keymap", SK_KEYMAP); + { + let mut keys_up_flex = map.start_vector("keys_up"); + for key in keys_up { + keys_up_flex.push(key); + } + } + { + let mut keys_down_flex = map.start_vector("keys_down"); + for key in keys_down { + keys_down_flex.push(key); + } + } + } + rx.send_data(&self.node.uid, fbb.take_buffer()).unwrap(); + } } } diff --git a/src/objects/input/sk.kmp b/src/objects/input/sk.kmp new file mode 100644 index 0000000..e5067df --- /dev/null +++ b/src/objects/input/sk.kmp @@ -0,0 +1,275 @@ +xkb_keymap { + +default xkb_keycodes "basic" { + minimum = 8; + maximum = 255; + + = 8; + = 9; + = 13; + = 16; + = 17; + = 18; + = 20; + = 27; + = 32; + = 35; + = 36; + = 37; + = 39; + = 38; + = 40; + = 33; + = 34; + = 42; + = 45; + = 46; + + <0> = 48; + <1> = 49; + <2> = 50; + <3> = 51; + <4> = 52; + <5> = 53; + <6> = 54; + <7> = 55; + <8> = 56; + <9> = 57; + + = 65; + = 66; + = 67; + = 68; + = 69; + = 70; + = 71; + = 72; + = 73; + = 74; + = 75; + = 76; + = 77; + = 78; + = 79; +

{ [ p, P ] }; + key { [ q, Q ] }; + key { [ r, R ] }; + key { [ s, S ] }; + key { [ t, T ] }; + key { [ u, U ] }; + key { [ v, V ] }; + key { [ w, W ] }; + key { [ x, X ] }; + key { [ y, Y ] }; + key { [ z, Z ] }; + + key { [ KP_0 ] }; + key { [ KP_1 ] }; + key { [ KP_2 ] }; + key { [ KP_3 ] }; + key { [ KP_4 ] }; + key { [ KP_5 ] }; + key { [ KP_6 ] }; + key { [ KP_7 ] }; + key { [ KP_8 ] }; + key { [ KP_9 ] }; + + key { [ F1 ] }; + key { [ F2 ] }; + key { [ F3 ] }; + key { [ F4 ] }; + key { [ F5 ] }; + key { [ F6 ] }; + key { [ F7 ] }; + key { [ F8 ] }; + key { [ F9 ] }; + key { [ F10 ] }; + key { [ F11 ] }; + key { [ F12 ] }; + + key { [ comma, less ] }; + key { [ period, greater ] }; + key { [ slash, question ] }; + key { [ backslash, bar ] }; + key { [ semicolon, colon ] }; + key { [ apostrophe ] }; + key { [ bracketleft, braceleft ] }; + key { [ bracketright, braceright ] }; + key { [ minus, underscore ] }; + key { [ equal, plus ] }; + key { [ grave, asciitilde ] }; + key { [ Super_L ] }; + key { [ Super_R ] }; + key { [ KP_Multiply ] }; + key { [ KP_Add ] }; + key { [ KP_Subtract ] }; + key { [ KP_Decimal ] }; + key { [ KP_Divide ] }; + + modifier_map Shift { }; + modifier_map Lock { }; + modifier_map Control { }; + modifier_map Mod1 { }; + modifier_map Mod4 { , }; +}; + +};

= 80; + = 81; + = 82; + = 83; + = 84; + = 85; + = 86; + = 87; + = 88; + = 89; + = 90; + + = 96; + = 97; + = 98; + = 99; + = 100; + = 101; + = 102; + = 103; + = 104; + = 105; + + = 112; + = 113; + = 114; + = 115; + = 116; + = 117; + = 118; + = 119; + = 120; + = 121; + = 122; + = 123; + + = 188; + = 190; + = 191; + = 220; + = 186; + = 222; + = 219; + = 221; + = 189; + = 187; + = 192; + = 91; + = 92; + = 106; + = 107; + = 109; + = 110; + = 111; +}; + +partial default xkb_types "basic" { + virtual_modifiers Alt; + + type "ONE_LEVEL" { + modifiers= none; + level_name[1]= "Any"; + }; + type "TWO_LEVEL" { + modifiers= Shift; + map[Shift]= 2; + level_name[1]= "Base"; + level_name[2]= "Shift"; + }; + type "ALPHABETIC" { + modifiers= Shift+Lock; + map[Shift]= 2; + map[Lock]= 2; + level_name[1]= "Base"; + level_name[2]= "Caps"; + }; + type "SHIFT+ALT" { + modifiers= Shift+Alt; + map[Shift+Alt]= 2; + level_name[1]= "Base"; + level_name[2]= "Shift+Alt"; + }; + type "PC_CONTROL_LEVEL2" { + modifiers= Control; + map[Control]= 2; + level_name[1]= "Base"; + level_name[2]= "Control"; + }; +}; + +partial default xkb_compatibility "basic" { + interpret.useModMapMods= AnyLevel; + interpret.repeat= False; + + interpret ISO_Level2_Latch+Exactly(Shift) { + useModMapMods=level1; + action= LatchMods(modifiers=Shift,clearLocks,latchToLock); + }; + interpret Caps_Lock+AnyOfOrNone(all) { + action= LockMods(modifiers=Lock); + }; + indicator "Caps Lock" { + whichModState= locked; + modifiers= Lock; + }; +}; + +default xkb_symbols "basic" { + name[Group1]="English (US)"; + key { [ BackSpace, BackSpace ] }; + key { [ Tab, ISO_Left_Tab ] }; + key { [ Return ] }; + key { [ Shift_L ] }; + key { [ Shift_R ] }; + key { [ Control_L ] }; + key { [ Control_R ] }; + key { [ Alt_L ] }; + key { [ Alt_R ] }; + key { [ Caps_Lock ] }; + key { [ Escape ] }; + key { [ space ] }; + key { [ End ] }; + key { [ Home ] }; + key { [ Left ] }; + key { [ Right ] }; + key { [ Up ] }; + key { [ Down ] }; + key { [ Page_Up ] }; + key { [ Page_Down ] }; + key { [ Print ] }; + key { [ Insert ] }; + key { [ Delete ] }; + + key <1> { [ 1, exclam ] }; + key <2> { [ 2, at ] }; + key <3> { [ 3, numbersign ] }; + key <4> { [ 4, dollar ] }; + key <5> { [ 5, percent ] }; + key <6> { [ 6, asciicircum ] }; + key <7> { [ 7, ampersand ] }; + key <8> { [ 8, asterisk ] }; + key <9> { [ 9, parenleft ] }; + key <0> { [ 0, parenright ] }; + + key { [ a, A ] }; + key { [ b, B ] }; + key { [ c, C ] }; + key { [ d, D ] }; + key { [ e, E ] }; + key { [ f, F ] }; + key { [ g, G ] }; + key { [ h, H ] }; + key { [ i, I ] }; + key { [ j, J ] }; + key { [ k, K ] }; + key { [ l, L ] }; + key { [ m, M ] }; + key { [ n, N ] }; + key { [ o, O ] }; + key