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