]> git.lizzy.rs Git - mt_client.git/blob - src/gfx.rs
Pause on escape
[mt_client.git] / src / gfx.rs
1 use crate::{GfxEvent::*, NetEvent};
2 use cgmath::Rad;
3 use std::time::Instant;
4 use tokio::sync::mpsc;
5 use winit::{
6     event::{DeviceEvent::*, Event::*, WindowEvent::*},
7     event_loop::ControlFlow::ExitWithCode,
8     platform::run_return::EventLoopExtRunReturn,
9     window::CursorGrabMode,
10 };
11
12 mod map;
13 mod media;
14 mod state;
15 mod util;
16
17 pub async fn run(
18     mut event_loop: winit::event_loop::EventLoop<crate::GfxEvent>,
19     net_events: mpsc::UnboundedSender<NetEvent>,
20 ) {
21     let window = winit::window::WindowBuilder::new()
22         .build(&event_loop)
23         .unwrap();
24
25     window.set_cursor_visible(false);
26
27     let mut state = state::State::new(&window).await;
28     let mut map = None;
29     let mut media = media::MediaMgr::new();
30
31     let mut nodedefs = None;
32
33     let mut last_frame = Instant::now();
34
35     let mut game_paused = false;
36
37     event_loop.run_return(move |event, _, flow| match event {
38         MainEventsCleared => window.request_redraw(),
39         RedrawRequested(id) if id == window.id() => {
40             let now = Instant::now();
41             let dt = now - last_frame;
42             last_frame = now;
43
44             state.update(dt);
45             net_events
46                 .send(NetEvent::PlayerPos(
47                     state.camera.position.into(),
48                     Rad(state.camera.yaw).into(),
49                     Rad(state.camera.pitch).into(),
50                 ))
51                 .ok();
52
53             use wgpu::SurfaceError::*;
54             match state.render(&map) {
55                 Ok(_) => {}
56                 Err(Lost) => state.configure_surface(),
57                 Err(OutOfMemory) => *flow = ExitWithCode(0),
58                 Err(err) => eprintln!("gfx error: {err:?}"),
59             }
60         }
61         WindowEvent {
62             ref event,
63             window_id: id,
64         } if id == window.id() => match event {
65             CloseRequested => *flow = ExitWithCode(0),
66             Resized(size) => state.resize(*size),
67             ScaleFactorChanged { new_inner_size, .. } => state.resize(**new_inner_size),
68             KeyboardInput {
69                 input:
70                     winit::event::KeyboardInput {
71                         virtual_keycode: Some(key),
72                         state: key_state,
73                         ..
74                     },
75                 ..
76             } => {
77                 use fps_camera::Actions;
78                 use winit::event::{ElementState, VirtualKeyCode as Key};
79
80                 if key == &Key::Escape && key_state == &ElementState::Pressed {
81                     game_paused = !game_paused;
82                     window.set_cursor_visible(game_paused);
83                 }
84
85                 if !game_paused {
86                     let actions = match key {
87                         Key::W => Actions::MOVE_FORWARD,
88                         Key::A => Actions::STRAFE_LEFT,
89                         Key::S => Actions::MOVE_BACKWARD,
90                         Key::D => Actions::STRAFE_RIGHT,
91                         Key::Space => Actions::FLY_UP,
92                         Key::LShift => Actions::FLY_DOWN,
93                         _ => Actions::empty(),
94                     };
95
96                     match key_state {
97                         ElementState::Pressed => state.camera.enable_actions(actions),
98                         ElementState::Released => state.camera.disable_action(actions),
99                     }
100                 }
101             }
102             _ => {}
103         },
104         DeviceEvent {
105             event: MouseMotion { delta },
106             ..
107         } => {
108             if !game_paused {
109                 state.camera.update_mouse(delta.0 as f32, delta.1 as f32);
110                 window
111                     .set_cursor_position(winit::dpi::PhysicalPosition::new(
112                         state.config.width / 2,
113                         state.config.height / 2,
114                     ))
115                     .ok();
116             }
117         }
118         UserEvent(event) => match event {
119             Close => *flow = ExitWithCode(0),
120             NodeDefs(defs) => nodedefs = Some(defs),
121             MapBlock(pos, blk) => {
122                 if let Some(map) = map.as_mut() {
123                     map.add_block(&mut state, pos, blk);
124                 }
125             }
126             Media(files, finished) => {
127                 media.add_server_media(files);
128
129                 if finished {
130                     map = Some(map::MapRender::new(
131                         &mut state,
132                         &media,
133                         nodedefs.take().unwrap_or_default(),
134                     ));
135
136                     net_events.send(NetEvent::Ready).ok();
137                 }
138             }
139             PlayerPos(pos, pitch, yaw) => {
140                 state.camera.position = pos.into();
141                 state.camera.pitch = Rad::<f32>::from(pitch).0;
142                 state.camera.yaw = Rad::<f32>::from(yaw).0;
143             }
144         },
145         _ => {}
146     });
147 }