]> git.lizzy.rs Git - mt_client.git/blobdiff - src/gfx.rs
Basic map rendering
[mt_client.git] / src / gfx.rs
diff --git a/src/gfx.rs b/src/gfx.rs
new file mode 100644 (file)
index 0000000..e3fb073
--- /dev/null
@@ -0,0 +1,141 @@
+use crate::{GfxEvent::*, NetEvent};
+use cgmath::Rad;
+use std::time::Instant;
+use tokio::sync::mpsc;
+use winit::{
+    event::{DeviceEvent::*, Event::*, WindowEvent::*},
+    event_loop::ControlFlow::ExitWithCode,
+    platform::run_return::EventLoopExtRunReturn,
+    window::CursorGrabMode,
+};
+
+mod map;
+mod media;
+mod state;
+mod util;
+
+pub async fn run(
+    mut event_loop: winit::event_loop::EventLoop<crate::GfxEvent>,
+    net_events: mpsc::UnboundedSender<NetEvent>,
+) {
+    let window = winit::window::WindowBuilder::new()
+        .build(&event_loop)
+        .unwrap();
+
+    window
+        .set_cursor_grab(CursorGrabMode::Locked)
+        .or_else(|_e| window.set_cursor_grab(CursorGrabMode::Confined))
+        .unwrap();
+
+    window.set_cursor_visible(false);
+
+    let mut state = state::State::new(&window).await;
+    let mut map = None;
+    let mut media = media::MediaMgr::new();
+
+    let mut nodedefs = None;
+
+    let mut last_frame = Instant::now();
+
+    event_loop.run_return(move |event, _, flow| match event {
+        MainEventsCleared => window.request_redraw(),
+        RedrawRequested(id) if id == window.id() => {
+            let now = Instant::now();
+            let dt = now - last_frame;
+            last_frame = now;
+
+            state.update(dt);
+            net_events
+                .send(NetEvent::PlayerPos(
+                    state.camera.position.into(),
+                    Rad(state.camera.yaw).into(),
+                    Rad(state.camera.pitch).into(),
+                ))
+                .ok();
+
+            use wgpu::SurfaceError::*;
+            match state.render(&map) {
+                Ok(_) => {}
+                Err(Lost) => state.configure_surface(),
+                Err(OutOfMemory) => *flow = ExitWithCode(0),
+                Err(err) => eprintln!("gfx error: {err:?}"),
+            }
+        }
+        WindowEvent {
+            ref event,
+            window_id: id,
+        } if id == window.id() => match event {
+            CloseRequested => *flow = ExitWithCode(0),
+            Resized(size) => state.resize(*size),
+            ScaleFactorChanged { new_inner_size, .. } => state.resize(**new_inner_size),
+            KeyboardInput {
+                input:
+                    winit::event::KeyboardInput {
+                        virtual_keycode: Some(key),
+                        state: key_state,
+                        ..
+                    },
+                ..
+            } => {
+                use fps_camera::Actions;
+                use winit::event::{ElementState::*, VirtualKeyCode as Key};
+
+                let actions = match key {
+                    Key::W => Actions::MOVE_FORWARD,
+                    Key::A => Actions::STRAFE_LEFT,
+                    Key::S => Actions::MOVE_BACKWARD,
+                    Key::D => Actions::STRAFE_RIGHT,
+                    Key::Space => Actions::FLY_UP,
+                    Key::LShift => Actions::FLY_DOWN,
+                    _ => Actions::empty(),
+                };
+
+                match key_state {
+                    Pressed => state.camera.enable_actions(actions),
+                    Released => state.camera.disable_action(actions),
+                }
+            }
+            _ => {}
+        },
+        DeviceEvent {
+            event: MouseMotion { delta },
+            ..
+        } => {
+            state.camera.update_mouse(delta.0 as f32, delta.1 as f32);
+            window
+                .set_cursor_position(winit::dpi::PhysicalPosition::new(
+                    state.config.width / 2,
+                    state.config.height / 2,
+                ))
+                .ok();
+        }
+        UserEvent(event) => match event {
+            Close => *flow = ExitWithCode(0),
+            NodeDefs(defs) => nodedefs = Some(defs),
+            MapBlock(pos, blk) => {
+                if let Some(map) = map.as_mut() {
+                    map.add_block(&mut state, pos, blk);
+                }
+            }
+            Media(files, finished) => {
+                media.add_server_media(files);
+
+                if finished {
+                    map = Some(map::MapRender::new(
+                        &mut state,
+                        &media,
+                        nodedefs.take().unwrap_or_default(),
+                    ));
+
+                    net_events.send(NetEvent::Ready).ok();
+                }
+            }
+            PlayerPos(pos, pitch, yaw) => {
+                state.camera.position = pos.into();
+                state.camera.pitch = Rad::<f32>::from(pitch).0;
+                state.camera.yaw = Rad::<f32>::from(yaw).0;
+            }
+        },
+        _ => {}
+    });
+}