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