1use {
2 crate::{
3 cx::Cx,
4 Margin,
5 Area,
6 HitOptions,
7 Hit,
8 SmallVec,
9 FingerDownEvent,
10 CxWindowPool,
11 DigitDevice,
12 KeyModifiers,
13 makepad_micro_serde::*,
14 makepad_math::*,
15 LiveId,
16 makepad_live_id::{live_id_num},
17 },
18 std::rc::Rc,
19};
20
21#[derive(Clone, Debug, Default, SerBin, DeBin)]
22pub struct XrController {
23 pub grip_pose: Pose,
24 pub aim_pose: Pose,
25 pub trigger: f32,
26 pub grip: f32,
27 pub buttons: u16,
28 pub stick: Vec2,
29}
30
31impl XrController{
32 pub const CLICK_X: u16 = 1<<0;
33 pub const CLICK_Y: u16 = 1<<1;
34 pub const CLICK_A: u16 = 1<<2;
35 pub const CLICK_B: u16 = 1<<3;
36 pub const CLICK_MENU: u16 = 1<<4;
37
38 pub const ACTIVE: u16 = 1<<5;
39 pub const CLICK_THUMBSTICK: u16 = 1<<6;
40
41 pub const TOUCH_X: u16 = 1<<7;
42 pub const TOUCH_Y: u16 = 1<<8;
43 pub const TOUCH_A: u16 = 1<<9;
44 pub const TOUCH_B: u16 = 1<<10;
45 pub const TOUCH_THUMBSTICK: u16 = 1<<11;
46 pub const TOUCH_TRIGGER: u16 = 1<<12;
47 pub const TOUCH_THUMBREST: u16 = 1<<13;
48 pub fn triggered(&self)->bool{ self.trigger>0.8}
49 pub fn active(&self)->bool{self.buttons & Self::ACTIVE != 0}
50
51 pub fn click_x(&self)->bool{self.buttons & Self::CLICK_X != 0}
52 pub fn click_y(&self)->bool{self.buttons & Self::CLICK_Y != 0}
53 pub fn click_a(&self)->bool{self.buttons & Self::CLICK_A != 0}
54 pub fn click_b(&self)->bool{self.buttons & Self::CLICK_B != 0}
55 pub fn click_thumbstick(&self)->bool{self.buttons & Self::CLICK_THUMBSTICK != 0}
56 pub fn click_menu(&self)->bool{self.buttons & Self::CLICK_MENU != 0}
57
58 pub fn touch_x(&self)->bool{self.buttons & Self::TOUCH_X != 0}
59 pub fn touch_y(&self)->bool{self.buttons & Self::TOUCH_Y != 0}
60 pub fn touch_a(&self)->bool{self.buttons & Self::TOUCH_A != 0}
61 pub fn touch_b(&self)->bool{self.buttons & Self::TOUCH_B != 0}
62 pub fn touch_thumbstick(&self)->bool{self.buttons & Self::TOUCH_THUMBSTICK != 0}
63 pub fn touch_trigger(&self)->bool{self.buttons & Self::TOUCH_TRIGGER != 0}
64 pub fn touch_thumbrest(&self)->bool{self.buttons & Self::TOUCH_THUMBREST != 0}
65}
66
67#[derive(Clone, Debug, Default, SerBin, DeBin)]
68pub struct XrHand{
69 pub flags: u8,
70 pub joints: [Pose;Self::JOINT_COUNT],
71 pub tips: [f32;5],
72 pub tips_active: u8,
73 pub aim_pose: Pose,
74 pub pinch: [u8;4]
75}
76
77impl XrHand{
78
79 pub fn in_view(&self)->bool{self.flags & Self::IN_VIEW != 0}
80 pub fn aim_valid(&self)->bool{self.flags & Self::AIM_VALID != 0}
81 pub fn menu_pressed(&self)->bool{self.flags & Self::MENU_PRESSED != 0}
82 pub fn dominant_hand(&self)->bool{self.flags & Self::DOMINANT_HAND != 0}
84
85 pub fn pinch_index(&self)->bool{self.flags & Self::PINCH_INDEX != 0}
86 pub fn pinch_middle(&self)->bool{self.flags & Self::PINCH_MIDDLE != 0}
87 pub fn pinch_ring(&self)->bool{self.flags & Self::PINCH_RING != 0}
88 pub fn pinch_little(&self)->bool{self.flags & Self::PINCH_LITTLE != 0}
89
90 pub fn pinch_only_little(&self)->bool{
91 self.pinch[Self::PINCH_STRENGTH_INDEX]<100 &&
92 self.pinch[Self::PINCH_STRENGTH_MIDDLE]<100 &&
93 self.pinch[Self::PINCH_STRENGTH_RING]<100 &&
94 self.pinch[Self::PINCH_STRENGTH_LITTLE]>160
95 }
96 pub fn pinch_only_index(&self)->bool{
97 self.pinch[Self::PINCH_STRENGTH_INDEX]>160 &&
98 self.pinch[Self::PINCH_STRENGTH_MIDDLE]<100 &&
99 self.pinch[Self::PINCH_STRENGTH_RING]<100 &&
100 self.pinch[Self::PINCH_STRENGTH_LITTLE]<100
101 }
102
103 pub fn pinch_not_index(&self)->bool{
104 self.pinch[Self::PINCH_STRENGTH_INDEX]<100 && (
105 self.pinch[Self::PINCH_STRENGTH_MIDDLE]>160 ||
106 self.pinch[Self::PINCH_STRENGTH_RING]>160 ||
107 self.pinch[Self::PINCH_STRENGTH_LITTLE]>160)
108 }
109
110 pub fn pinch_strength_index(&self)->f32{self.pinch[Self::PINCH_STRENGTH_INDEX] as f32 / u8::MAX as f32}
111 pub fn pinch_strength_middle(&self)->f32{self.pinch[Self::PINCH_STRENGTH_MIDDLE] as f32 / u8::MAX as f32}
112 pub fn pinch_strength_ring(&self)->f32{self.pinch[Self::PINCH_STRENGTH_RING] as f32 / u8::MAX as f32}
113 pub fn pinch_strength_pinky(&self)->f32{self.pinch[Self::PINCH_STRENGTH_LITTLE] as f32 / u8::MAX as f32}
114
115 pub const IN_VIEW: u8 = 1<<0;
116 pub const AIM_VALID: u8 = 1<<1;
117 pub const PINCH_INDEX: u8 = 1<<2;
118 pub const PINCH_MIDDLE: u8 = 1<<3;
119 pub const PINCH_RING: u8 = 1<<4;
120 pub const PINCH_LITTLE: u8 = 1<<5;
121 pub const DOMINANT_HAND: u8 = 1<<6;
122 pub const MENU_PRESSED : u8 = 1<<7;
123
124 pub const PINCH_STRENGTH_INDEX: usize = 0;
125 pub const PINCH_STRENGTH_MIDDLE: usize = 1;
126 pub const PINCH_STRENGTH_RING: usize = 2;
127 pub const PINCH_STRENGTH_LITTLE: usize = 3;
128
129 pub const JOINT_COUNT: usize = 21;
130 pub const CENTER: usize = 0;
131 pub const WRIST: usize = 1;
132 pub const THUMB_BASE: usize = 2;
133 pub const THUMB_KNUCKLE1: usize = 3;
134 pub const THUMB_KNUCKLE2: usize = 4;
135 pub const INDEX_BASE: usize = 5;
136 pub const INDEX_KNUCKLE1: usize = 6;
137 pub const INDEX_KNUCKLE2: usize = 7;
138 pub const INDEX_KNUCKLE3: usize = 8;
139 pub const MIDDLE_BASE: usize = 9;
140 pub const MIDDLE_KNUCKLE1: usize = 10;
141 pub const MIDDLE_KNUCKLE2: usize = 11;
142 pub const MIDDLE_KNUCKLE3: usize = 12;
143 pub const RING_BASE: usize = 13;
144 pub const RING_KNUCKLE1: usize = 14;
145 pub const RING_KNUCKLE2: usize = 15;
146 pub const RING_KNUCKLE3: usize = 16;
147 pub const LITTLE_BASE: usize = 17;
148 pub const LITTLE_KNUCKLE1: usize = 18;
149 pub const LITTLE_KNUCKLE2: usize = 19;
150 pub const LITTLE_KNUCKLE3: usize = 20;
151
152 pub const END_KNUCKLES: [usize;5] = [
153 Self::THUMB_KNUCKLE2,
154 Self::INDEX_KNUCKLE3,
155 Self::MIDDLE_KNUCKLE3,
156 Self::RING_KNUCKLE3,
157 Self::LITTLE_KNUCKLE3
158 ];
159
160 pub fn end_knuckles(&self)->[&Pose;5]{
161 [
162 &self.joints[XrHand::THUMB_KNUCKLE2],
163 &self.joints[XrHand::INDEX_KNUCKLE3],
164 &self.joints[XrHand::MIDDLE_KNUCKLE3],
165 &self.joints[XrHand::RING_KNUCKLE3],
166 &self.joints[XrHand::LITTLE_KNUCKLE3],
167 ]
168 }
169
170 pub const THUMB_TIP: usize = 0;
171 pub const INDEX_TIP: usize = 1;
172 pub const MIDDLE_TIP: usize = 2;
173 pub const RING_TIP: usize = 3;
174 pub const LITTLE_TIP: usize = 4;
175
176 pub fn tip_active(&self,tip:usize)->bool{
177 self.tips_active & (1<<tip) != 0
178 }
179
180 fn tip_pos(&self,tip:usize, knuckle:usize)->Vec3{
181 let pos = vec4(0.0,0.0,-self.tips[tip],1.0);
182 self.joints[knuckle].to_mat4().transform_vec4(pos).to_vec3()
183 }
184
185 pub fn tip_pos_thumb(&self)->Vec3{self.tip_pos(0, XrHand::THUMB_KNUCKLE2)}
186 pub fn tip_pos_index(&self)->Vec3{self.tip_pos(0, XrHand::INDEX_KNUCKLE3)}
187 pub fn tip_pos_middle(&self)->Vec3{self.tip_pos(0, XrHand::MIDDLE_KNUCKLE3)}
188 pub fn tip_pos_ring(&self)->Vec3{self.tip_pos(0, XrHand::RING_KNUCKLE3)}
189 pub fn tip_pos_little(&self)->Vec3{self.tip_pos(0, XrHand::LITTLE_KNUCKLE3)}
190
191}
192
193#[derive(Clone, Debug)]
194pub struct XrFingerTip{
195 pub index: usize,
196 pub is_left: bool,
197 pub pos: Vec3,
198}
199
200#[derive(Clone, Debug)]
201pub struct XrLocalEvent{
202 pub finger_tips: SmallVec<[XrFingerTip;10]>,
203 pub update: XrUpdateEvent,
204 pub modifiers: KeyModifiers,
205 pub time: f64,
206}
207
208#[derive(Clone, Copy, Debug, Default, SerBin, DeBin, PartialEq)]
209pub struct XrAnchor{
210 pub left: Vec3,
211 pub right: Vec3,
212}
213
214impl XrAnchor{
215 pub fn to_quat(&self)->Quat{
216 let mut forward = self.right - self.left;
217 forward.y = 0.0;
218 Quat::look_rotation(forward, vec3(0.0,1.0,0.0))
219 }
220
221 pub fn to_quat_rev(&self)->Quat{
222 let mut forward = self.left - self.right;
223 forward.y = 0.0;
224 Quat::look_rotation(forward, vec3(0.0,1.0,0.0))
225 }
226
227 pub fn to_mat4(&self)->Mat4{
228 self.to_pose().to_mat4()
229 }
230
231 pub fn to_pose(&self)->Pose{
232 Pose{position: (self.left+self.right)/2.0, orientation:self.to_quat()}
233 }
234
235 pub fn mapping_to(&self, other:&XrAnchor)->Mat4{
236 Mat4::mul(&self.to_pose().to_mat4().invert(), &other.to_pose().to_mat4())
237 }
238}
239
240#[derive(Clone, Debug, Default, SerBin, DeBin)]
241pub struct XrState{
242 pub time: f64,
243 pub head_pose: Pose,
244 pub order_counter: u8,
245 pub anchor: Option<XrAnchor>,
246 pub left_controller: XrController,
247 pub right_controller: XrController,
248 pub left_hand: XrHand,
249 pub right_hand: XrHand,
250}
251impl XrState{
252 pub fn from_lerp(a:&XrState, b:&XrState, f:f32)->Self{
253 Self{
254 order_counter: b.order_counter,
255 time: (b.time - a.time)*f as f64 + a.time,
256 head_pose: Pose::from_lerp(a.head_pose, b.head_pose, f),
257 anchor: b.anchor,
258 left_controller: b.left_controller.clone(),
259 right_controller: b.right_controller.clone(),
260 left_hand: b.left_hand.clone(),
261 right_hand: b.right_hand.clone(),
262 }
263 }
264
265 pub fn vec_in_head_space(&self,pos:Vec3)->Vec3{
266 self.head_pose.to_mat4().transform_vec4(pos.to_vec4()).to_vec3()
267 }
268
269 pub fn scene_anchor_pose(&self)->Option<Pose>{
270 if let Some(_anchor) = &self.anchor{
271 None
273 }
274 else{
275 None
276 }
277 }
278
279 pub fn hands(&self)->[&XrHand;2]{
280 [&self.left_hand, &self.right_hand]
281 }
282 pub fn controllers(&self)->[&XrController;2]{
283 [&self.left_controller, &self.right_controller]
284 }
285}
286
287
288#[derive(Clone, Debug)]
289pub struct XrUpdateEvent {
290 pub state: Rc<XrState>,
291 pub last: Rc<XrState>,
292}
293
294impl XrUpdateEvent{
295
296 pub fn clicked_x(&self)->bool{self.state.left_controller.click_x() && !self.last.left_controller.click_x()}
297 pub fn clicked_y(&self)->bool{self.state.left_controller.click_y() && !self.last.left_controller.click_y()}
298 pub fn clicked_a(&self)->bool{self.state.right_controller.click_a() && !self.last.right_controller.click_a()}
299 pub fn clicked_b(&self)->bool{self.state.right_controller.click_b() && !self.last.right_controller.click_b()}
300 pub fn clicked_left_thumbstick(&self)->bool{self.state.left_controller.click_thumbstick() && !self.last.left_controller.click_thumbstick()}
301 pub fn clicked_right_thumbstick(&self)->bool{self.state.right_controller.click_thumbstick() && !self.last.right_controller.click_thumbstick()}
302 pub fn clicked_menu(&self)->bool{self.state.left_controller.click_menu() && !self.last.left_controller.click_menu()}
303 pub fn menu_pressed(&self)->bool{self.state.left_hand.menu_pressed() && !self.last.left_hand.menu_pressed()}
304
305}
306
307impl XrLocalEvent{
308
309
310 pub fn from_update_event(e:&XrUpdateEvent, mat:&Mat4)->XrLocalEvent{
311 let _inv = mat.invert();
315 let finger_tips = SmallVec::new();
317 for (_hindex, hand) in [&e.state.left_hand, &e.state.right_hand].iter().enumerate(){
318 if hand.in_view(){
319 for (_index,_joint) in hand.joints.iter().enumerate(){
320 }
330 }
331 }
332
333 XrLocalEvent{
334 finger_tips,
335 modifiers: Default::default(),
336 time: e.state.time,
337 update: e.clone(),
338 }
339 }
340
341 pub fn hits_with_options_and_test<F>(&self, cx: &mut Cx, area: Area, options: HitOptions, hit_test:F) -> Hit
342 where F: Fn(DVec2, &Rect, &Option<Margin>)->bool
343 {
344 let rect = area.clipped_rect(cx);
345 for tip in &self.finger_tips{
346 let abs = tip.pos.to_vec2().into();
347 if hit_test(abs, &rect, &options.margin) {
350 if tip.pos.z <20.0 && tip.pos.z > -30.0{
351 let device = DigitDevice::XrHand { is_left: tip.is_left, index: tip.index };
352 let digit_id = live_id_num!(xrfinger, tip.index as u64 + if tip.is_left{10} else{0}).into();
353 cx.fingers.capture_digit(digit_id, area, options.sweep_area, self.time, abs);
354 return Hit::FingerDown(FingerDownEvent {
355 window_id: CxWindowPool::id_zero(),
356 abs,
357 digit_id,
358 device,
359 tap_count: cx.fingers.tap_count(),
360 modifiers: self.modifiers,
361 time: self.time,
362 rect,
363 });
364 }
365 }
366 }
367 return Hit::Nothing
395 }
396}