1use {
2 crate::{
3 makepad_derive_widget::*,
4 makepad_draw::*,
5 widget::*,
6 },
7};
8
9use crate::makepad_draw::shader::draw_cube::DrawCube;
10
11live_design!{
12 link widgets;
13 use link::theme::*;
14 use link::shaders::*;
15
16 pub XrHands = {{XrHands}} {
17
18 draw_bullet:{
19 color: #0
20
21 fn get_color(self, dp: float)->vec4{
22 let ambient = vec3(0.2,0.2,0.2)
23 let color = self.color.xyz * dp * self.color.w + ambient;
24 return vec4(Pal::iq1(self.life-self.time+self.index*0.1)*1.0,0.0);}
26 fn get_size(self)->vec3{
27 let size = pow(max(3.0-(self.life),0.0)/4.0,1.);
28 return self.cube_size * size*vec3(0.1,1.2*sin(self.life),(6-self.index+1)*1.0);
29 }
30 fn get_pos(self)->vec3{
31 let travel = self.life * 0.4;
32 return vec3(0.0, 0.0, -travel)
33 }
34 cube_size:vec3(0.01,0.01,0.015);
35 }
36 draw_knuckle:{
37 color: #fff;
38 cube_size:vec3(0.01,0.01,0.015);
39 }
40 draw_tip:{
41 color: #f00;
42 cube_size:vec3(0.01,0.01,0.001);
43 }
44 draw_align:{
45 color:#f00
46 cube_size: vec3(0.02,0.02,0.02)
47 }
48 draw_test:{
49 color:#f00
50 cube_size: vec3(0.02,0.02,0.02)
51 }
52 draw_head:{
53 color:#fff
54 cube_size: vec3(0.2,0.1,0.05)
55 }
56 draw_grip:{
57 color: #777,
58 cube_size: vec3(0.05,0.05,0.05)
59 }
60 draw_aim:{
61 color: #777,
62 cube_size: vec3(0.05,0.05,0.05)
63 }
64
65 }
66}
67
68struct Bullet{
69 shot_at: f64,
70 index: usize,
71 pose: Pose,
72}
73#[derive(Default)]
74struct Bullets{
75 last_fired: f64,
76 bullets: Vec<Bullet>,
77}
78
79pub struct XrPeer{
80 id: LiveId,
81 ahead: bool,
82 min_lag: f64,
83 states: Vec<XrState>,
84 bullets: Bullets
85}
86
87impl XrPeer{
88 fn state(&self)->&XrState{
89 self.states.last().as_ref().unwrap()
90 }
91 fn tween(&self, _host_time:f64)->XrState{
92 if self.states.len()>=2{
94 self.states[0].clone()
95 }
96 else{
97 self.states[0].clone()
98 }
99 }
100}
101
102impl Bullets{
103 fn draw(&mut self, cx:&mut Cx3d, cube:&mut DrawCube, xr_state:&XrState, anchor_map:&Mat4){
104 if xr_state.time < self.last_fired{ self.last_fired = xr_state.time;
106 }
107 if xr_state.time - self.last_fired > 0.005 {
108 for hand in xr_state.hands(){
109 if !hand.in_view(){
110 continue
111 }
112 for (i,pose) in hand.end_knuckles().iter().enumerate(){
113 if !hand.tip_active(i){continue;}
114
115 self.last_fired = xr_state.time;
116 self.bullets.push(Bullet{
117 shot_at: xr_state.time,
118 index: i,
119 pose:**pose
120 });
121 if self.bullets.len()>4500{
122 self.bullets.remove(0);
123 }
124 }
125 }
126 }
127 for bullet in &self.bullets{
128 let mat = Mat4::mul(&bullet.pose.to_mat4(), anchor_map);
129 cube.index = bullet.index as f32;
130 cube.life = (xr_state.time - bullet.shot_at) as f32;
131 cube.transform = mat;
132 cube.depth_clip = 1.0;
133 cube.draw(cx);
134 }
135 }
136}
137
138const ALIGN_MODE: f64 = 0.4;
139struct AlignMode{
140 anchor: XrAnchor,
141}
142
143#[derive(Live, LiveHook, Widget)]
144pub struct XrHands {
145 #[redraw] #[rust(DrawList::new(cx))] draw_list: DrawList,
146 #[live] draw_align: DrawCube,
147 #[live] draw_test: DrawCube,
148 #[live] draw_head: DrawCube,
149 #[area] #[live] draw_knuckle: DrawCube,
150 #[live] draw_controller: DrawCube,
151 #[live] draw_bullet: DrawCube,
152 #[live] draw_grip: DrawCube,
153 #[live] draw_aim: DrawCube,
154 #[live] draw_tip: DrawCube,
155
156 #[live] label: DrawText,
157 #[rust] peers: Vec<XrPeer>,
158 #[rust] align_last_click: f64,
159 #[rust] align_mode: Option<AlignMode>,
160 #[rust] bullets: Bullets,
161}
162
163impl XrHands{
164
165 pub fn leave_peer(&mut self, _cx:&mut Cx, id:LiveId){
166 self.peers.retain(|v| v.id != id);
167 }
168
169 pub fn update_peer(&mut self, _cx:&mut Cx, id:LiveId, state:XrState, e:&XrUpdateEvent){
170 if let Some(peer) = self.peers.iter_mut().find(|v| v.id == id){
171 peer.ahead = state.time > e.state.time;
172 peer.min_lag = peer.min_lag.min((state.time - e.state.time).abs());
173 let peer_state = peer.state();
174 if state.order_counter>peer_state.order_counter ||
175 peer_state.order_counter - state.order_counter>128{
176 peer.states.insert(0, state);
177 }
178 peer.states.truncate(2);
179 }
180 else{
181 self.peers.push(XrPeer{
182 id,
183 ahead: false,
184 min_lag: 1.0,
185 states: vec![state],
186 bullets:Bullets::default()
187 });
188 }
189 }
190
191 fn handle_alignment(&mut self, cx:&mut Cx, e:&XrUpdateEvent){
192 if e.menu_pressed() || e.clicked_menu(){
195 if e.state.time - self.align_last_click < ALIGN_MODE{
196 if let Some(align_mode) = &mut self.align_mode{
198 cx.xr_set_local_anchor(align_mode.anchor);
200 self.align_mode = None;
201 }
202 else if self.align_mode.is_none(){
203 let anchor = if let Some(anchor) = &e.state.anchor{
205 *anchor
206 }
207 else{
208 XrAnchor{
209 left: e.state.vec_in_head_space(vec3(-0.2,0.0,-0.4)),
210 right: e.state.vec_in_head_space(vec3(0.2,0.0,-0.4))
211 }
212 };
213
214 self.align_mode = Some(AlignMode{
216 anchor,
217 });
218 }
219
220 }
221 self.align_last_click = e.state.time;
222 }
223 if let Some(align_mode) = &mut self.align_mode{
225 if e.state.left_hand.pinch_not_index(){
226 align_mode.anchor.left = e.state.left_hand.tip_pos_thumb();
227 }
228 if e.state.right_hand.pinch_not_index(){
229 align_mode.anchor.right = e.state.right_hand.tip_pos_thumb();
230 }
231 if e.state.left_controller.triggered(){
232 align_mode.anchor.left = e.state.left_controller.aim_pose.position;
233 }
234 if e.state.right_controller.triggered(){
235 align_mode.anchor.right = e.state.right_controller.aim_pose.position;
236 }
237 }
238 }
239
240 fn draw_alignment(&mut self, cx:&mut Cx3d, _xr_state:&XrState){
241 if let Some(align) = &self.align_mode{
242 let cube = &mut self.draw_align;
245 cube.color = color!(#00f);
246 cube.transform = Pose::new(align.anchor.to_quat(),align.anchor.left).to_mat4();
247 cube.depth_clip = 1.0;
248 cube.draw(cx);
249 cube.color = color!(#0f0);
250 cube.transform = Pose::new(align.anchor.to_quat_rev(),align.anchor.right).to_mat4();
251 cube.draw(cx);
252 }
254 }
255}
256
257impl Widget for XrHands {
258 fn handle_event(&mut self, cx: &mut Cx,event:&Event, _scope:&mut Scope){
259 if let Event::XrUpdate(e) = event{
260 self.handle_alignment(cx, e);
261 self.redraw(cx);
262 }
263 }
264 fn draw_3d(&mut self, cx: &mut Cx3d, _scope:&mut Scope)->DrawStep{
265 self.draw_list.begin_always(cx);
266
267 fn draw_hands(
268 cx: &mut Cx3d,
269 cube:&mut DrawCube,
270 tip: &mut DrawCube,
271 transform: &Mat4,
272 xr_state:&XrState,
273 ){
274 for hand in [&xr_state.left_hand, &xr_state.right_hand]{
276 if hand.in_view(){
277 for (_index,joint) in hand.joints.iter().enumerate(){
278 let mat = Mat4::mul(&joint.to_mat4(), transform);
279 cube.cube_pos = vec3(0.0,0.0,0.0);
280 cube.transform = mat;
281 cube.depth_clip = 0.0;
282 cube.draw(cx);
283 }
284 }
285 for (i, knuckle) in XrHand::END_KNUCKLES.iter().enumerate(){
286 if !hand.tip_active(i){continue;}
287 let joint = &hand.joints[*knuckle];
288 let mat = Mat4::mul(&joint.to_mat4(), transform);
289 tip.cube_pos = vec3(0.0,0.0,-hand.tips[i]);
290 tip.transform = mat;
291 tip.depth_clip = 0.0;
292 tip.draw(cx);
293 }
294 }
295 }
296
297 fn _draw_controllers(
298 cx: &mut Cx3d,
299 draw_aim:&mut DrawCube,
300 draw_grip: &mut DrawCube,
301 transform: &Mat4,
302 xr_state:&XrState,
303 ){
304 let mata = Mat4::mul(&xr_state.left_controller.aim_pose.to_mat4(), transform);
306 draw_aim.cube_pos = vec3(0.0,0.0,0.0);
307 draw_aim.transform = mata;
308 draw_aim.depth_clip = 0.0;
309 draw_aim.draw(cx);
310
311 let mata = Mat4::mul(&xr_state.right_controller.grip_pose.to_mat4(), transform);
312 draw_grip.cube_pos = vec3(0.0,0.0,0.0);
313 draw_grip.transform = mata;
314 draw_grip.depth_clip = 0.0;
315 draw_grip.draw(cx);
316 }
317
318
319 fn draw_head(
320 cx: &mut Cx3d,
321 cube:&mut DrawCube,
322 transform: &Mat4,
323 xr_state:&XrState,
324 ){
325 let mata = Mat4::mul(&xr_state.head_pose.to_mat4(), transform);
326 cube.color = vec4(1.0,1.0,1.0,1.0);
327 cube.cube_pos = vec3(0.0,0.0,0.0);
328 cube.transform = mata;
329 cube.depth_clip = 0.0;
330 cube.draw(cx);
331 }
332
333 fn _draw_democube(
334 cx: &mut Cx3d,
335 cube:&mut DrawCube,
336 anchor:&XrAnchor,
337 ){
338 let _speed = 32.0;
339 cube.color = vec4(1.0,1.0,1.0,1.0);
341 cube.cube_size = vec3(0.1,0.1,0.1);
342 cube.cube_pos = vec3(0.0,0.1,0.0);
343 cube.transform = anchor.to_mat4();
344
345 cube.depth_clip = 1.0;
352 cube.draw(cx);
353 }
354 let xr_state = cx.draw_event.xr_state.as_ref().unwrap();
356
357 self.draw_alignment(cx, xr_state);
358
359 draw_hands(cx, &mut self.draw_knuckle, &mut self.draw_tip, &Mat4::identity(), &xr_state);
360
361 self.bullets.draw(cx, &mut self.draw_bullet, &xr_state, &Mat4::identity());
363
364 for peer in &mut self.peers{
365 let peer_state = peer.tween(xr_state.time);
366 if let Some(other_anchor) = &peer_state.anchor{
367 if let Some(my_anchor) = &xr_state.anchor{
368 let anchor_map = other_anchor.mapping_to(my_anchor);
370 draw_hands(cx, &mut self.draw_knuckle, &mut self.draw_tip, &anchor_map, &peer_state);
371
372 draw_head(cx, &mut self.draw_head, &anchor_map, &peer_state);
373
374 peer.bullets.draw(cx, &mut self.draw_bullet, &peer_state, &anchor_map)
375 }
376 }
377 else{
378 draw_hands(cx, &mut self.draw_knuckle, &mut self.draw_tip, &Mat4::identity(), &peer_state)
379 }
380 }
381 self.draw_list.end(cx);
383 DrawStep::done()
384 }
385}
386