cleaned up some stuff
This commit is contained in:
parent
c2c645ee39
commit
62e5bd3c0d
@ -1,6 +1,6 @@
|
||||
use cgmath::{Vector3, Point3, InnerSpace, Deg, Rad};
|
||||
|
||||
use crate::Input;
|
||||
use crate::input::Input;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Camera {
|
||||
@ -53,7 +53,7 @@ impl Camera {
|
||||
}
|
||||
|
||||
pub fn update_rot(&mut self, input: &Input, sf: f32) {
|
||||
// doesn't need dt because the input is not continuous.
|
||||
// doesn't need dt because the input is not continuous.
|
||||
let (dx, dy) = input.mouse_moved;
|
||||
|
||||
self.rot_x += Deg((dx / input.dots_per_deg) * sf);
|
||||
|
59
src/input.rs
Normal file
59
src/input.rs
Normal file
@ -0,0 +1,59 @@
|
||||
use winit::event::{VirtualKeyCode, ElementState};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Input {
|
||||
pub amount_left: f32,
|
||||
pub amount_right: f32,
|
||||
pub amount_forward: f32,
|
||||
pub amount_backward: f32,
|
||||
pub amount_up: f32,
|
||||
pub amount_down: f32,
|
||||
pub mouse_moved: (f32, f32),
|
||||
pub speed: f32,
|
||||
pub dots_per_deg: f32,
|
||||
}
|
||||
|
||||
impl Input {
|
||||
pub fn new(speed: f32, dots_per_360deg: f32) -> Self {
|
||||
Self {
|
||||
amount_left: 0.0,
|
||||
amount_right: 0.0,
|
||||
amount_forward: 0.0,
|
||||
amount_backward: 0.0,
|
||||
amount_up: 0.0,
|
||||
amount_down: 0.0,
|
||||
mouse_moved: (0.0, 0.0),
|
||||
speed,
|
||||
dots_per_deg: dots_per_360deg / 360.0,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn process_key(&mut self, key: VirtualKeyCode, state: ElementState) {
|
||||
let amount = if state == ElementState::Pressed { 1.0 } else { 0.0 };
|
||||
match key {
|
||||
VirtualKeyCode::I | VirtualKeyCode::Up => {
|
||||
self.amount_forward = amount;
|
||||
}
|
||||
VirtualKeyCode::J | VirtualKeyCode::Left => {
|
||||
self.amount_left = amount;
|
||||
}
|
||||
VirtualKeyCode::K | VirtualKeyCode::Down => {
|
||||
self.amount_backward = amount;
|
||||
}
|
||||
VirtualKeyCode::L | VirtualKeyCode::Right => {
|
||||
self.amount_right = amount;
|
||||
}
|
||||
VirtualKeyCode::Space => {
|
||||
self.amount_up = amount;
|
||||
}
|
||||
VirtualKeyCode::Semicolon => {
|
||||
self.amount_down = amount;
|
||||
}
|
||||
_ => ()
|
||||
};
|
||||
}
|
||||
|
||||
pub fn process_mouse_motion(&mut self, (dx, dy): (f64, f64)) {
|
||||
self.mouse_moved = (dx as f32, dy as f32);
|
||||
}
|
||||
}
|
240
src/main.rs
240
src/main.rs
@ -41,116 +41,81 @@ var inches_per_1dg = inches_per_360dg / 360;
|
||||
var dots_per_1dg = inches_per_1dg * dpi;
|
||||
*/
|
||||
|
||||
use {winit::{event as Event, event_loop::{ControlFlow, EventLoop}, window::WindowBuilder}, std::{cmp::Ordering, process::ExitCode}};
|
||||
use {
|
||||
std::{process::ExitCode, time::Instant},
|
||||
winit::{
|
||||
event_loop::{ControlFlow, EventLoop},
|
||||
window::WindowBuilder,
|
||||
event::{VirtualKeyCode, ElementState, WindowEvent}
|
||||
},
|
||||
};
|
||||
|
||||
mod state;
|
||||
use std::time::Instant;
|
||||
mod camera;
|
||||
mod input;
|
||||
|
||||
use input::Input;
|
||||
use state::State;
|
||||
|
||||
mod camera;
|
||||
use camera::Camera;
|
||||
use winit::{event::{VirtualKeyCode, ElementState, KeyboardInput, WindowEvent, MouseButton}, window::Window};
|
||||
fn handle_window_event(state: &mut State, event: WindowEvent) -> ControlFlow {
|
||||
use WindowEvent::{*, KeyboardInput as KeyboardInputEvent};
|
||||
use winit::event::{KeyboardInput, MouseButton};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Input {
|
||||
amount_left: f32,
|
||||
amount_right: f32,
|
||||
amount_forward: f32,
|
||||
amount_backward: f32,
|
||||
amount_up: f32,
|
||||
amount_down: f32,
|
||||
mouse_moved: (f32, f32),
|
||||
speed: f32,
|
||||
dots_per_deg: f32,
|
||||
}
|
||||
|
||||
impl Input {
|
||||
pub fn new(speed: f32, dots_per_360deg: f32) -> Self {
|
||||
Self {
|
||||
amount_left: 0.0,
|
||||
amount_right: 0.0,
|
||||
amount_forward: 0.0,
|
||||
amount_backward: 0.0,
|
||||
amount_up: 0.0,
|
||||
amount_down: 0.0,
|
||||
mouse_moved: (0.0, 0.0),
|
||||
speed,
|
||||
dots_per_deg: dots_per_360deg / 360.0,
|
||||
match event {
|
||||
MouseInput { state: elem_state, button, .. } => {
|
||||
if button == MouseButton::Left && elem_state == ElementState::Pressed {
|
||||
if !state.is_fullscreen() {
|
||||
state.set_fullscreen(true);
|
||||
} else if !state.is_focused() {
|
||||
// is fullscreen but not focused
|
||||
state.set_focus(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn process_keyboard(&mut self, key: VirtualKeyCode, state: ElementState) {
|
||||
let amount = if state == ElementState::Pressed { 1.0 } else { 0.0 };
|
||||
match key {
|
||||
VirtualKeyCode::I | VirtualKeyCode::Up => {
|
||||
self.amount_forward = amount;
|
||||
}
|
||||
VirtualKeyCode::J | VirtualKeyCode::Left => {
|
||||
self.amount_left = amount;
|
||||
}
|
||||
VirtualKeyCode::K | VirtualKeyCode::Down => {
|
||||
self.amount_backward = amount;
|
||||
}
|
||||
VirtualKeyCode::L | VirtualKeyCode::Right => {
|
||||
self.amount_right = amount;
|
||||
}
|
||||
VirtualKeyCode::Space => {
|
||||
self.amount_up = amount;
|
||||
}
|
||||
VirtualKeyCode::Semicolon => {
|
||||
self.amount_down = amount;
|
||||
}
|
||||
_ => ()
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
fn set_fullscreen(to: bool, window: &Window, cursor_locked: &mut bool) -> bool {
|
||||
if to {
|
||||
fn area(size: winit::dpi::PhysicalSize<u32>) -> u32 {
|
||||
size.width * size.height
|
||||
CursorLeft { .. } if state.is_focused() => {
|
||||
state.set_focus(false);
|
||||
}
|
||||
let video_modes = window.current_monitor().expect("no monitor detected").video_modes();
|
||||
let video_mode = video_modes.max_by(|x, y| {
|
||||
if area(x.size()) > area(y.size()) {
|
||||
return Ordering::Greater;
|
||||
} else if area(x.size()) < area(y.size()) {
|
||||
return Ordering::Less;
|
||||
CloseRequested => {
|
||||
return ControlFlow::Exit;
|
||||
}
|
||||
Resized(physical_size) => {
|
||||
state.reconfigure(Some(physical_size));
|
||||
}
|
||||
ScaleFactorChanged { new_inner_size, .. } => {
|
||||
state.reconfigure(Some(*new_inner_size));
|
||||
}
|
||||
|
||||
KeyboardInputEvent {
|
||||
input:
|
||||
KeyboardInput {
|
||||
virtual_keycode: Some(key),
|
||||
state: elem_state,
|
||||
..
|
||||
},
|
||||
..
|
||||
} => match key {
|
||||
VirtualKeyCode::Escape if elem_state == ElementState::Pressed => {
|
||||
// toggle fullscreen
|
||||
state.set_fullscreen(!state.is_fullscreen());
|
||||
}
|
||||
if x.refresh_rate_millihertz() > y.refresh_rate_millihertz() {
|
||||
return Ordering::Greater;
|
||||
} else {
|
||||
return Ordering::Less;
|
||||
}
|
||||
}).expect("no video modes");
|
||||
window.set_fullscreen(
|
||||
Some(winit::window::Fullscreen::Exclusive(video_mode.clone()))
|
||||
);
|
||||
window.set_cursor_visible(false);
|
||||
window.set_cursor_grab(winit::window::CursorGrabMode::Confined).expect("failed to lock cursor");
|
||||
} else {
|
||||
window.set_fullscreen(None);
|
||||
window.set_cursor_visible(true);
|
||||
window.set_cursor_grab(winit::window::CursorGrabMode::None).expect("failed to unlock cursor");
|
||||
_ => state.process_key(key, elem_state),
|
||||
}
|
||||
|
||||
_ => ()
|
||||
}
|
||||
|
||||
*cursor_locked = to;
|
||||
return to;
|
||||
return ControlFlow::Poll;
|
||||
}
|
||||
|
||||
fn real_main() -> Result<(), &'static str> {
|
||||
let event_loop = EventLoop::new();
|
||||
let window = WindowBuilder::new()
|
||||
.with_title("game")
|
||||
.with_fullscreen(None)
|
||||
.build(&(event_loop))
|
||||
.map_err(|_| "failed to create window")?;
|
||||
|
||||
let mut cursor_locked = false;
|
||||
let mut fullscreen = set_fullscreen(false, &(window), &mut(cursor_locked));
|
||||
|
||||
let mut state = State::new(window)?;
|
||||
let mut input = Input::new(1.0, 7368.0);
|
||||
let mut state = State::new(window, Input::new(1.0, 7368.0))?;
|
||||
|
||||
let mut total_elapsed = 0.0;
|
||||
let mut frames = 0;
|
||||
@ -158,85 +123,44 @@ fn real_main() -> Result<(), &'static str> {
|
||||
let mut prev_render = Instant::now();
|
||||
|
||||
event_loop.run(move |event, _, flow| {
|
||||
use winit::event::{Event::*, DeviceEvent::MouseMotion};
|
||||
|
||||
let window = state.window();
|
||||
*flow = ControlFlow::Poll;
|
||||
|
||||
match event {
|
||||
Event::Event::WindowEvent { window_id, event } if window_id == window.id() => match event {
|
||||
WindowEvent::MouseInput { state, button, .. } => {
|
||||
if button == MouseButton::Left && state == ElementState::Pressed {
|
||||
if !fullscreen {
|
||||
fullscreen = set_fullscreen(true, &(window), &mut(cursor_locked));
|
||||
} else if !cursor_locked {
|
||||
window.set_cursor_grab(winit::window::CursorGrabMode::Confined).expect("failed to lock cursor");
|
||||
window.set_cursor_visible(false);
|
||||
cursor_locked = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
WindowEvent::CursorLeft { .. } if fullscreen => {
|
||||
window.set_cursor_grab(winit::window::CursorGrabMode::None).expect("failed to unlock cursor");
|
||||
window.set_cursor_visible(true);
|
||||
cursor_locked = false;
|
||||
}
|
||||
WindowEvent::CloseRequested => {
|
||||
*flow = ControlFlow::Exit;
|
||||
}
|
||||
WindowEvent::Resized(physical_size) => {
|
||||
state.reconfigure(Some(physical_size));
|
||||
}
|
||||
WindowEvent::ScaleFactorChanged { new_inner_size, .. } => {
|
||||
state.reconfigure(Some(*new_inner_size));
|
||||
}
|
||||
|
||||
WindowEvent::KeyboardInput {
|
||||
input:
|
||||
KeyboardInput {
|
||||
virtual_keycode: Some(key),
|
||||
state,
|
||||
..
|
||||
},
|
||||
..
|
||||
} => match key {
|
||||
VirtualKeyCode::Escape if state == ElementState::Pressed => {
|
||||
fullscreen = set_fullscreen(!fullscreen, &(window), &mut(cursor_locked));
|
||||
}
|
||||
_ => input.process_keyboard(key, state),
|
||||
}
|
||||
|
||||
_ => ()
|
||||
}
|
||||
Event::Event::DeviceEvent {
|
||||
event: Event::DeviceEvent::MouseMotion { delta, }, ..
|
||||
} if cursor_locked => {
|
||||
input.mouse_moved.0 = delta.0 as f32;
|
||||
input.mouse_moved.1 = delta.1 as f32;
|
||||
WindowEvent { window_id, event: window_event } if window_id == window.id() => {
|
||||
*flow = handle_window_event(&mut(state), window_event);
|
||||
}
|
||||
|
||||
Event::Event::MainEventsCleared => {
|
||||
DeviceEvent {
|
||||
event: MouseMotion { delta, }, ..
|
||||
} if state.is_focused() => {
|
||||
state.process_mouse_motion(delta);
|
||||
}
|
||||
|
||||
MainEventsCleared => {
|
||||
let mut elapsed = prev_render.elapsed().as_secs_f32();
|
||||
total_elapsed += elapsed;
|
||||
prev_render = Instant::now();
|
||||
prev_render = Instant::now();
|
||||
|
||||
const TIMESTEP: f32 = 1.0 / 60.0;
|
||||
const TIMESTEP: f32 = 1.0 / 60.0;
|
||||
|
||||
let mut interpolate = 1.0;
|
||||
let sf = interpolate / (elapsed / TIMESTEP);
|
||||
let mut interpolate = 1.0;
|
||||
let sf = interpolate / (elapsed / TIMESTEP);
|
||||
|
||||
while elapsed >= TIMESTEP {
|
||||
state.camera.update_pos(&(input), TIMESTEP);
|
||||
state.camera.update_rot(&(input), sf);
|
||||
elapsed -= TIMESTEP;
|
||||
interpolate -= sf;
|
||||
}
|
||||
state.camera.update_pos(&(input), elapsed);
|
||||
state.camera.update_rot(&(input), interpolate);
|
||||
input.mouse_moved = (0.0, 0.0);
|
||||
while elapsed >= TIMESTEP {
|
||||
state.update_camera(TIMESTEP, sf);
|
||||
|
||||
state.window().request_redraw();
|
||||
elapsed -= TIMESTEP;
|
||||
interpolate -= sf;
|
||||
}
|
||||
state.update_camera(elapsed, interpolate);
|
||||
state.process_mouse_motion((0.0, 0.0));
|
||||
|
||||
state.window().request_redraw();
|
||||
}
|
||||
Event::Event::RedrawRequested(_) => {
|
||||
state.update();
|
||||
RedrawRequested(_) => {
|
||||
match state.render() {
|
||||
Err(wgpu::SurfaceError::Lost | wgpu::SurfaceError::Outdated) => state.reconfigure(None),
|
||||
Err(wgpu::SurfaceError::OutOfMemory) => *flow = ControlFlow::ExitWithCode(1),
|
||||
@ -251,8 +175,8 @@ fn real_main() -> Result<(), &'static str> {
|
||||
frames = 0;
|
||||
total_elapsed = 0.0;
|
||||
}
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
_ => (),
|
||||
};
|
||||
|
||||
return;
|
||||
|
90
src/state.rs
90
src/state.rs
@ -2,11 +2,15 @@ use cgmath::Deg;
|
||||
use winit::window::Window;
|
||||
use wgpu::{util::DeviceExt};
|
||||
|
||||
use crate::{Camera, camera::CameraUniform};
|
||||
use crate::{camera::*, Input};
|
||||
|
||||
pub struct State {
|
||||
input: Input,
|
||||
|
||||
window: Window,
|
||||
size: winit::dpi::PhysicalSize<u32>,
|
||||
fullscreen: bool,
|
||||
focused: bool,
|
||||
|
||||
surface: wgpu::Surface,
|
||||
device: wgpu::Device,
|
||||
@ -16,7 +20,7 @@ pub struct State {
|
||||
|
||||
vertex_buffer: wgpu::Buffer,
|
||||
|
||||
pub camera: Camera,
|
||||
camera: Camera,
|
||||
camera_uniform: CameraUniform,
|
||||
camera_bind_group: wgpu::BindGroup,
|
||||
}
|
||||
@ -29,7 +33,7 @@ struct Vertex {
|
||||
}
|
||||
|
||||
impl State {
|
||||
pub fn new(window: Window) -> Result<Self, &'static str> {
|
||||
pub fn new(window: Window, input: Input) -> Result<Self, &'static str> {
|
||||
let size = window.inner_size();
|
||||
|
||||
let instance = wgpu::Instance::new(wgpu::InstanceDescriptor {
|
||||
@ -176,6 +180,10 @@ impl State {
|
||||
}));
|
||||
|
||||
return Ok(Self {
|
||||
input,
|
||||
|
||||
fullscreen: false,
|
||||
focused: false,
|
||||
window,
|
||||
size,
|
||||
|
||||
@ -197,6 +205,63 @@ impl State {
|
||||
return &(self.window);
|
||||
}
|
||||
|
||||
pub fn set_focus(&mut self, to: bool) {
|
||||
assert!((!self.fullscreen && !to) || self.fullscreen);
|
||||
assert!(to != self.focused);
|
||||
|
||||
let window = self.window();
|
||||
if to {
|
||||
window.set_cursor_visible(false);
|
||||
window.set_cursor_grab(winit::window::CursorGrabMode::Confined).expect("failed to lock cursor");
|
||||
} else {
|
||||
window.set_cursor_visible(true);
|
||||
window.set_cursor_grab(winit::window::CursorGrabMode::None).expect("failed to unlock cursor");
|
||||
}
|
||||
|
||||
self.focused = to;
|
||||
return;
|
||||
}
|
||||
pub fn is_focused(&self) -> bool {
|
||||
return self.focused;
|
||||
}
|
||||
|
||||
pub fn set_fullscreen(&mut self, to: bool) {
|
||||
assert!(to != self.fullscreen);
|
||||
|
||||
use std::cmp::Ordering;
|
||||
let window = self.window();
|
||||
if to {
|
||||
fn area(size: winit::dpi::PhysicalSize<u32>) -> u32 {
|
||||
size.width * size.height
|
||||
}
|
||||
let video_modes = window.current_monitor().expect("no monitor detected").video_modes();
|
||||
let video_mode = video_modes.max_by(|x, y| {
|
||||
if area(x.size()) > area(y.size()) {
|
||||
return Ordering::Greater;
|
||||
} else if area(x.size()) < area(y.size()) {
|
||||
return Ordering::Less;
|
||||
}
|
||||
if x.refresh_rate_millihertz() > y.refresh_rate_millihertz() {
|
||||
return Ordering::Greater;
|
||||
} else {
|
||||
return Ordering::Less;
|
||||
}
|
||||
}).expect("no video modes");
|
||||
window.set_fullscreen(
|
||||
Some(winit::window::Fullscreen::Exclusive(video_mode.clone()))
|
||||
);
|
||||
} else {
|
||||
window.set_fullscreen(None);
|
||||
}
|
||||
|
||||
self.fullscreen = to;
|
||||
self.set_focus(to);
|
||||
return;
|
||||
}
|
||||
pub fn is_fullscreen(&self) -> bool {
|
||||
return self.fullscreen;
|
||||
}
|
||||
|
||||
pub fn reconfigure(&mut self, new_size: Option<winit::dpi::PhysicalSize<u32>>) {
|
||||
let new_size = new_size.unwrap_or(self.size);
|
||||
assert!(new_size.width > 0 && new_size.height > 0);
|
||||
@ -205,13 +270,12 @@ impl State {
|
||||
self.config.height = new_size.height;
|
||||
self.surface.configure(&(self.device), &(self.config));
|
||||
self.camera.reconfigure(new_size);
|
||||
}
|
||||
|
||||
pub fn update(&mut self) {
|
||||
self.camera_uniform.set_view_projection_matrix(&(self.queue), &(self.camera));
|
||||
return;
|
||||
}
|
||||
|
||||
pub fn render(&mut self) -> Result<(), wgpu::SurfaceError> {
|
||||
self.camera_uniform.set_view_projection_matrix(&(self.queue), &(self.camera));
|
||||
let output = self.surface.get_current_texture()?;
|
||||
let view = output.texture.create_view(&(wgpu::TextureViewDescriptor::default()));
|
||||
let mut encoder = self.device.create_command_encoder(&(wgpu::CommandEncoderDescriptor {
|
||||
@ -243,4 +307,18 @@ impl State {
|
||||
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
pub fn update_camera(&mut self, dt: f32, sf: f32) {
|
||||
self.camera.update_pos(&(self.input), dt);
|
||||
self.camera.update_rot(&(self.input), sf);
|
||||
return;
|
||||
}
|
||||
pub fn process_key(&mut self, key: winit::event::VirtualKeyCode, state: winit::event::ElementState) {
|
||||
self.input.process_key(key, state);
|
||||
return;
|
||||
}
|
||||
pub fn process_mouse_motion(&mut self, delta: (f64, f64)) {
|
||||
self.input.process_mouse_motion(delta);
|
||||
return;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user